【问题标题】:OpenCV detecting TV screen using cameraOpenCV使用相机检测电视屏幕
【发布时间】:2023-04-02 11:30:02
【问题描述】:

我正在使用 iPhone 摄像头检测电视屏幕。我目前的方法是逐像素比较后续帧并跟踪累积差异。结果是二值图像,如图所示。

对我来说,这看起来像一个矩形,但 OpenCV 不这么认为。它的侧面并不完全笔直,有时甚至会有更多的颜色渗色,使检测变得困难。这是我尝试检测矩形的 OpenCV 代码,因为我对 OpenCV 不是很熟悉,它是从我找到的一些示例中复制而来的。

uint32_t *ptr = (uint32_t*)CVPixelBufferGetBaseAddress(buffer);
cv::Mat image((int)width, (int)height, CV_8UC4, ptr); // unsigned 8-bit values for 4 channels (ARGB)

cv::Mat image2 = [self matFromPixelBuffer:buffer];

std::vector<std::vector<cv::Point>>squares;

// blur will enhance edge detection

cv::Mat blurred(image2);
GaussianBlur(image2, blurred, cvSize(3,3), 0);//change from median blur to gaussian for more accuracy of square detection

cv::Mat gray0(blurred.size(), CV_8U), gray;

std::vector<std::vector<cv::Point> > contours;

// find squares in every color plane of the image
for (int c = 0; c < 3; c++) {
    int ch[] = {c, 0};
    mixChannels(&blurred, 1, &gray0, 1, ch, 1);
    
    // try several threshold levels
    const int threshold_level = 2;
    for (int l = 0; l < threshold_level; l++) {
        // Use Canny instead of zero threshold level!
        // Canny helps to catch squares with gradient shading
        if (l == 0) {
            Canny(gray0, gray, 10, 20, 3); //
            
            // Dilate helps to remove potential holes between edge segments
            dilate(gray, gray, cv::Mat(), cv::Point(-1,-1));
        } else {
            gray = gray0 >= (l+1) * 255 / threshold_level;
        }
        
        // Find contours and store them in a list
        findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
        
        // Test contours
        std::vector<cv::Point> approx;
        int biggestSize = 0;
        for (size_t i = 0; i < contours.size(); i++) {
            // approximate contour with accuracy proportional
            // to the contour perimeter
            approxPolyDP(cv::Mat(contours[i]), approx, arcLength(cv::Mat(contours[i]), true)*0.02, true);
            if (approx.size() != 4)
                continue;
            
            // Note: absolute value of an area is used because
            // area may be positive or negative - in accordance with the
            // contour orientation
            int areaSize = fabs(contourArea(cv::Mat(approx)));
            if (approx.size() == 4 && areaSize > biggestSize)
                biggestSize = areaSize;
            cv::RotatedRect boundingRect = cv::minAreaRect(approx);
            float aspectRatio = boundingRect.size.width /  boundingRect.size.height;

            cv::Rect boundingRect2 = cv::boundingRect(approx);
            float aspectRatio2 = (float)boundingRect2.width / (float)boundingRect2.height;
            
            bool convex = isContourConvex(cv::Mat(approx));
            if (approx.size() == 4 &&
                fabs(contourArea(cv::Mat(approx))) > minArea &&
                (aspectRatio >= minAspectRatio && aspectRatio <= maxAspectRatio) &&
                isContourConvex(cv::Mat(approx))) {
                double maxCosine = 0;
                
                for (int j = 2; j < 5; j++) {
                    double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
                    maxCosine = MAXIMUM(maxCosine, cosine);
                }
                double area = fabs(contourArea(cv::Mat(approx)));
                if (maxCosine < 0.3) {
                    squares.push_back(approx);
                }
            }
        }
    }

经过 Canny-step 后,图像如下所示:

对我来说似乎很好,但由于某种原因没有检测到矩形。谁能解释我的参数是否有问题?

我的第二种方法是使用 OpenCV Hough 线检测,基本上使用与上面相同的代码,对于 Canny 图像,然后我调用 HoughLines 函数。它给了我很多行,因为我必须降低阈值来检测垂直线。结果如下所示:

问题是有很多行。如何找出与第一张图片所示蓝色矩形边相接触的线条?

或者有没有更好的方法来检测屏幕?

【问题讨论】:

    标签: opencv hough-transform canny-operator straight-line-detection


    【解决方案1】:

    首先,找到最大面积轮廓reference,然后计算最小面积矩形reference,将轮廓面积除以矩形面积,如果它足够接近1,那么你的轮廓类似于矩形。这将是您所需的轮廓和矩形。

    【讨论】:

    • 感谢您的回复,非常聪明的方法。实现了这一点,但生成的矩形太大,它包括所有带有颜色溢出的区域。我需要准确地检测角落。
    猜你喜欢
    • 2016-09-23
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 2016-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多