#include #include #include #include #include #include static std::string last_error; extern "C" { // 图像解码 Image* cv_imdecode(const unsigned char* buf, size_t size) { try { std::vector data(buf, buf + size); cv::Mat mat = cv::imdecode(data, cv::IMREAD_COLOR); if (mat.empty()) { last_error = "无法解码图像"; return nullptr; } Image* img = new Image(); img->width = mat.cols; img->height = mat.rows; img->channels = mat.channels(); size_t data_size = mat.total() * mat.elemSize(); img->data = (unsigned char*)malloc(data_size); memcpy(img->data, mat.data, data_size); return img; } catch (const std::exception& e) { last_error = e.what(); return nullptr; } } // 释放图像 void cv_image_free(Image* img) { if (img) { if (img->data) { free(img->data); } delete img; } } // 滑块缺口匹配 int cv_slider_match(const Image* target, const Image* background, int* out_x) { try { cv::Mat target_mat(target->height, target->width, CV_8UC3, target->data); cv::Mat bg_mat(background->height, background->width, CV_8UC3, background->data); cv::Mat target_gray, bg_gray; cv::cvtColor(target_mat, target_gray, cv::COLOR_BGR2GRAY); cv::cvtColor(bg_mat, bg_gray, cv::COLOR_BGR2GRAY); // 模板匹配 cv::Mat result; cv::matchTemplate(bg_gray, target_gray, result, cv::TM_CCOEFF_NORMED); double min_val, max_val; cv::Point min_loc, max_loc; cv::minMaxLoc(result, &min_val, &max_val, &min_loc, &max_loc); *out_x = max_loc.x; return 0; } catch (const std::exception& e) { last_error = e.what(); return -1; } } // 阴影滑块匹配 int cv_slider_comparison(const Image* target, const Image* background, int* out_x) { try { cv::Mat target_mat(target->height, target->width, CV_8UC3, target->data); cv::Mat bg_mat(background->height, background->width, CV_8UC3, background->data); // 转灰度 cv::Mat target_gray, bg_gray; cv::cvtColor(target_mat, target_gray, cv::COLOR_BGR2GRAY); cv::cvtColor(bg_mat, bg_gray, cv::COLOR_BGR2GRAY); // Canny 边缘检测 cv::Mat target_edges, bg_edges; cv::Canny(target_gray, target_edges, 50, 150); cv::Canny(bg_gray, bg_edges, 50, 150); // 模板匹配 cv::Mat result; cv::matchTemplate(bg_edges, target_edges, result, cv::TM_CCOEFF_NORMED); double min_val, max_val; cv::Point min_loc, max_loc; cv::minMaxLoc(result, &min_val, &max_val, &min_loc, &max_loc); *out_x = max_loc.x; return 0; } catch (const std::exception& e) { last_error = e.what(); return -1; } } // 检测旋转角度 float cv_detect_rotation(const Image* img) { try { cv::Mat mat(img->height, img->width, CV_8UC3, img->data); // 转灰度 cv::Mat gray; cv::cvtColor(mat, gray, cv::COLOR_BGR2GRAY); // 使用霍夫圆变换检测圆心 cv::Mat blurred; cv::GaussianBlur(gray, blurred, cv::Size(5, 5), 0); std::vector circles; cv::HoughCircles(blurred, circles, cv::HOUGH_GRADIENT, 1, blurred.rows / 8, 100, 30, 0, 0); if (circles.empty()) { return 0.0f; } // 简化处理:返回 0 度 // 实际实现需要更复杂的特征点匹配 return 0.0f; } catch (const std::exception& e) { last_error = e.what(); return 0.0f; } } // 图像相似度比较 float cv_compare_similarity(const Image* img1, const Image* img2) { try { cv::Mat mat1(img1->height, img1->width, CV_8UC3, img1->data); cv::Mat mat2(img2->height, img2->width, CV_8UC3, img2->data); // 确保 same size if (mat1.size() != mat2.size()) { cv::resize(mat2, mat2, mat1.size()); } // 计算 histogram cv::Mat hsv1, hsv2; cv::cvtColor(mat1, hsv1, cv::COLOR_BGR2HSV); cv::cvtColor(mat2, hsv2, cv::COLOR_BGR2HSV); int h_bins = 50, s_bins = 60; int histSize[] = {h_bins, s_bins}; float h_ranges[] = {0, 180}; float s_ranges[] = {0, 256}; const float* ranges[] = {h_ranges, s_ranges}; int channels[] = {0, 1}; cv::Mat hist1, hist2; cv::calcHist(&hsv1, 1, channels, cv::Mat(), hist1, 2, histSize, ranges); cv::calcHist(&hsv2, 1, channels, cv::Mat(), hist2, 2, histSize, ranges); cv::normalize(hist1, hist1, 0, 1, cv::NORM_MINMAX); cv::normalize(hist2, hist2, 0, 1, cv::NORM_MINMAX); double similarity = cv::compareHist(hist1, hist2, cv::HISTCMP_CORREL); return (float)similarity; } catch (const std::exception& e) { last_error = e.what(); return 0.0f; } } const char* cv_get_last_error() { return last_error.c_str(); } } // extern "C"