网站前台功能模块介绍郑州网站建设一汉狮网络
/**
  * 从二值图像中识别黑色矩形并统计数量
  * @param binaryImage 输入的二值图像(黑色区域为前景,白色为背景)
  * @param minArea 最小轮廓面积阈值,用于过滤噪声
  * @param outputImage 可选输出图像,用于可视化检测结果
  * @return 当检测到的矩形数量 > 3 时返回true,否则返回false
  */
 bool detectBlackRectangles(const cv::Mat& binaryImage, double minArea = 500, cv::Mat* outputImage = nullptr) {
     // 确保输入图像是二值图像
     CV_Assert(binaryImage.type() == CV_8UC1);
     
     // 复制输入图像用于处理
     cv::Mat processedImage = binaryImage.clone();
     
     // 形态学操作:开运算和闭运算,去除噪声并填充轮廓
     cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
     cv::morphologyEx(processedImage, processedImage, cv::MORPH_OPEN, kernel);
     cv::morphologyEx(processedImage, processedImage, cv::MORPH_CLOSE, kernel);
     
     // 查找轮廓
     std::vector<std::vector<cv::Point>> contours;
     std::vector<cv::Vec4i> hierarchy;
     cv::findContours(processedImage, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
     
     // 过滤轮廓并统计符合条件的矩形数量
     int validContourCount = 0;
     
     // 如果需要输出图像,创建彩色副本
     cv::Mat colorOutput;
     if (outputImage != nullptr) {
         cv::cvtColor(binaryImage, colorOutput, cv::COLOR_GRAY2BGR);
     }
     
     for (size_t i = 0; i < contours.size(); i++) {
         // 计算轮廓面积,过滤小面积噪声
         double area = cv::contourArea(contours[i]);
         if (area < minArea) continue;
         
         // 近似轮廓为多边形
         std::vector<cv::Point> approx;
         cv::approxPolyDP(contours[i], approx, 0.02 * cv::arcLength(contours[i], true), true);
         
         // 检查是否为矩形(3-6个顶点,不严格要求)
         if (approx.size() >= 3 && approx.size() <= 6) {
             validContourCount++;
             
             // 如果需要,绘制轮廓和边界框
             if (outputImage != nullptr) {
                 cv::drawContours(colorOutput, contours, i, cv::Scalar(0, 255, 0), 2);
                 cv::Rect rect = cv::boundingRect(contours[i]);
                 cv::rectangle(colorOutput, rect, cv::Scalar(0, 0, 255), 2);
             }
         }
     }
     
     // 如果需要,设置输出图像
     if (outputImage != nullptr) {
         *outputImage = colorOutput;
     }
     
     // 返回标志位:轮廓数量是否大于3
     return (validContourCount > 3);
 }
