OpenCV 使用摄像头检测电视屏幕

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

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

Original image

对我来说这看起来像一个矩形,但 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 之后图像看起来像这样:

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

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

Hough lines

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

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

最佳答案

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

关于OpenCV 使用摄像头检测电视屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47175206/

相关文章:

opencv - 读取图像并保存,增加图像大小

c++ - OpenCV 复制图像的一部分

Python opencv 概率霍夫线变换 - TypeError : object of type 'NoneType' has no len()

Python OpenCV : Hough Transform does not detect obvious lines

python - 我在使用 opencv python 使用坐标对在图像上绘制线条时遇到问题

c++ - OpenCV stereoRectify 扭曲图像

opencv - 筛选与冲浪。哪个更准确?

c++ - 用数组替换 malloc

c++ - OpenCV - 计算图像的边缘强度

python - 求叶子的周长