diff --git a/cotton_color.cpp b/cotton_color.cpp index f8624bb..7060728 100644 --- a/cotton_color.cpp +++ b/cotton_color.cpp @@ -3,133 +3,124 @@ #include #include #include -#include // 包含文件对话框相关的函数 +#include // 鍖呭惈鏂囦欢瀵硅瘽妗嗙浉鍏崇殑鍑芥暟 using namespace cv; using namespace std; /** - * @brief 鲜艳色彩检测函数,通过饱和度阈值检测输入图像中鲜艳的颜色区域。 + * @brief 椴滆壋缁胯壊妫娴嬪嚱鏁帮紝閫氳繃鎸囧畾鐨 Lab 鑹插僵鑼冨洿妫娴嬭緭鍏ュ浘鍍忎腑鐨勭豢鑹插尯鍩熴 * - * @param inputImage 输入图像,类型为 cv::Mat,要求为 BGR 色彩空间。 - * @param outputImage 输出图像,类型为 cv::Mat,输出图像将标记出鲜艳颜色区域,原始图像尺寸。 - * @param params 参数映射,用于传递各种可配置的参数,如饱和度阈值等。 + * @param inputImage 杈撳叆鍥惧儚锛岀被鍨嬩负 cv::Mat锛岃姹備负 BGR 鑹插僵绌洪棿銆 + * @param outputImage 杈撳嚭鍥惧儚锛岀被鍨嬩负 cv::Mat锛岃緭鍑哄浘鍍忓皢鍖呭惈妫娴嬪埌鐨勭豢鑹插尯鍩熴 + * @param params 鍙傛暟鏄犲皠锛岀敤浜庝紶閫掑悇绉嶅彲閰嶇疆鐨勫弬鏁帮紝濡傜豢鑹查槇鍊肩瓑銆 */ +void vibrantGreenDetection(const Mat& inputImage, Mat& outputImage, const map& params) { + // 浠庡弬鏁版槧灏勪腑鑾峰彇缁胯壊闃堝 + int green = params.at("green"); + + // 灏嗚緭鍏ュ浘鍍忎粠 BGR 杞崲涓 Lab + Mat lab_image; + cvtColor(inputImage, lab_image, cv::COLOR_BGR2Lab); + + // 瀹氫箟鍋忕豢鑹茬殑 Lab 鑼冨洿锛堝叿浣撳煎彲鑳介渶瑕佽皟鏁达級 + Scalar lower_green_lab(101, 101, 95); + Scalar upper_green_lab(135, 120, green); + + // 鍒涘缓鎺╄啘 + Mat mask_lab; + inRange(lab_image, lower_green_lab, upper_green_lab, mask_lab); + + // 閫氳繃鎺╄啘鎻愬彇鍋忕豢鑹查儴鍒嗭紝灏嗙粨鏋滃瓨鍌ㄥ湪 outputImage 涓 + bitwise_and(inputImage, inputImage, outputImage, mask_lab); +} void vibrantColorDetection(const Mat& inputImage, Mat& outputImage, const map& params) { - // 从参数映射中获取饱和度阈值 + // 浠庡弬鏁版槧灏勪腑鑾峰彇楗卞拰搴﹂槇鍊 int saturationThreshold = params.at("saturationThreshold"); - // 将输入图像从 BGR 转换为 HSV + // 灏嗚緭鍏ュ浘鍍忎粠 BGR 杞崲涓 HSV Mat hsvImage; cvtColor(inputImage, hsvImage, COLOR_BGR2HSV); - // 分离 HSV 图像的各个通道 + // 鍒嗙 HSV 鍥惧儚鐨勫悇涓氶亾 Mat channels[3]; split(hsvImage, channels); - // 获取饱和度通道 (S) + // 鑾峰彇楗卞拰搴﹂氶亾 (S) Mat saturation = channels[1]; - // 创建输出图像,将饱和度大于阈值的区域标记为杂质 + // 鍒涘缓杈撳嚭鍥惧儚锛屽皢楗卞拰搴﹀ぇ浜庨槇鍊肩殑鍖哄煙鏍囪涓烘潅璐 outputImage = Mat::zeros(inputImage.size(), CV_8UC1); - // 对饱和度图像应用阈值处理 + // 瀵归ケ鍜屽害鍥惧儚搴旂敤闃堝煎鐞 threshold(saturation, outputImage, saturationThreshold, 255, THRESH_BINARY); } +string openFileDialog() { + // 鍒濆鍖栨枃浠堕夋嫨瀵硅瘽妗 + OPENFILENAME ofn; // 鏂囦欢瀵硅瘽妗嗙粨鏋 + wchar_t szFile[260]; // 瀛樺偍閫夋嫨鐨勬枃浠惰矾寰 -/** - * @brief 打开文件对话框,返回选中文件的路径。 - * - * @return 选中文件的完整路径,类型为 std::wstring。如果用户取消选择,返回空字符串。 - */ -std::wstring openFileDialog() { - // 初始化文件选择对话框 - OPENFILENAMEW ofn; // 使用宽字符版本的结构 - wchar_t szFile[260] = {0}; // 存储选择的文件路径 - - // 设置 OPENFILENAMEW 结构的默认值 + // 璁剧疆 OPENFILENAME 缁撴瀯鐨勯粯璁ゅ ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = NULL; - ofn.lpstrFile = szFile; // 设置文件路径缓冲区 + ofn.lpstrFile = szFile; ofn.nMaxFile = sizeof(szFile) / sizeof(szFile[0]); ofn.lpstrFilter = L"Image Files\0*.BMP;*.JPG;*.JPEG;*.PNG;*.GIF\0All Files\0*.*\0"; ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = NULL; // 不需要单独的文件名 + ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = NULL; // 使用默认初始目录 - ofn.lpstrTitle = L"Select an image file"; // 对话框标题 + ofn.lpstrInitialDir = NULL; + ofn.lpstrTitle = L"Select an image file"; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - // 打开文件选择对话框 - if (GetOpenFileNameW(&ofn) == TRUE) { - return szFile; // 返回选中的文件路径 + // 鎵撳紑鏂囦欢閫夋嫨瀵硅瘽妗 + if (GetOpenFileName(&ofn) == TRUE) { + // 灏 wchar_t 杞崲涓 string + wstring ws(szFile); + string filePath(ws.begin(), ws.end()); + return filePath; } - return L""; // 如果用户取消,返回空字符串 + return ""; // 濡傛灉鐢ㄦ埛鍙栨秷锛岃繑鍥炵┖瀛楃涓 } -/** - * @brief 读取图像文件,支持 Unicode 路径。 - * - * @return 加载的图像,类型为 cv::Mat。如果加载失败,返回空的 Mat。 - */ + Mat readImage() { - // 读取输入图像路径 - std::wstring imagePath = openFileDialog(); + // 璇诲彇杈撳叆鍥惧儚 + string imagePath = openFileDialog(); if (imagePath.empty()) { - wcout << L"No file selected or user cancelled." << endl; + cout << "No file selected or user cancelled." << endl; return Mat(); } - // 使用 Windows API 打开文件 - HANDLE hFile = CreateFileW(imagePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - wcout << L"Error: Could not open file." << endl; - return Mat(); - } - - // 获取文件大小 - LARGE_INTEGER fileSize; - if (!GetFileSizeEx(hFile, &fileSize)) { - wcout << L"Error: Could not get file size." << endl; - CloseHandle(hFile); - return Mat(); - } - - if (fileSize.QuadPart > MAXDWORD) { - wcout << L"Error: File size too large." << endl; - CloseHandle(hFile); - return Mat(); - } - - DWORD dwFileSize = static_cast(fileSize.QuadPart); - - // 读取文件内容到缓冲区 - std::vector buffer(dwFileSize); - DWORD bytesRead = 0; - if (!ReadFile(hFile, buffer.data(), dwFileSize, &bytesRead, NULL) || bytesRead != dwFileSize) { - wcout << L"Error: Could not read file." << endl; - CloseHandle(hFile); - return Mat(); - } - - CloseHandle(hFile); - - // 使用 OpenCV 从内存缓冲区读取图像 - Mat image = imdecode(buffer, IMREAD_COLOR); + // 浣跨敤 OpenCV 璇诲彇閫変腑鐨勫浘鐗 + Mat image = imread(imagePath); if (image.empty()) { - wcout << L"Error: Could not decode image." << endl; + cout << "Error: Could not load image." << endl; return Mat(); } return image; } +// 杈呭姪鍑芥暟锛岀敤浜庤皟鏁村浘鍍忓ぇ灏忓苟鏄剧ず锛屾敮鎸佺瓑姣斾緥鏀惧ぇ +void showImage(const string& windowName, const Mat& img, double scaleFactor = 1.0) { + Mat resizedImg; + int newWidth = static_cast(img.cols * scaleFactor); + int newHeight = static_cast(img.rows * scaleFactor); + + // 璋冩暣鍥惧儚澶у皬 + resize(img, resizedImg, Size(newWidth, newHeight)); + + // 鏄剧ず鍥惧儚 + imshow(windowName, resizedImg); +} + int main() { - // 读取输入图像 + // 璇诲彇杈撳叆鍥惧儚 Mat inputImage = readImage(); if (inputImage.empty()) { @@ -137,21 +128,24 @@ int main() { return -1; } - // 创建输出图像 + // 鍒涘缓杈撳嚭鍥惧儚 Mat outputImage; - // 使用 map 模拟参数传递 + // 浣跨敤 map 妯℃嫙 JSON 鍙傛暟浼犻 map params; - params["saturationThreshold"] = 100; // 设置饱和度阈值为 100 + params["green"] = 134; // 璁剧疆缁胯壊闃堝 - // 调用鲜艳颜色检测函数 - vibrantColorDetection(inputImage, outputImage, params); + // 璋冪敤椴滆壋缁胯壊妫娴嬪嚱鏁 + vibrantGreenDetection(inputImage, outputImage, params); - // 显示原图和检测到的鲜艳区域 - imshow("Original Image", inputImage); - imshow("Detected Vibrant Colors", outputImage); + // 瀹氫箟缂╂斁鍥犲瓙锛1.0 琛ㄧず鍘熷澶у皬锛>1.0 琛ㄧず鏀惧ぇ锛<1.0 琛ㄧず缂╁皬 + double scaleFactor = 1.5; // 灏嗗浘鍍忔斁澶1.5鍊 - // 等待用户按键 + // 鏄剧ず鍘熷浘鍜屾娴嬪埌鐨勭豢鑹插尯鍩燂紝浣跨敤缂╂斁鍥犲瓙 + showImage("Original Image", inputImage, scaleFactor); + showImage("Detected Vibrant Green", outputImage, scaleFactor); + + // 绛夊緟鐢ㄦ埛鎸夐敭 waitKey(0); return 0; }