【问题标题】:OpenCV C++: Convert big block of white pixels to blackOpenCV C++:将大块白色像素转换为黑色
【发布时间】:2020-05-25 09:18:59
【问题描述】:

我是 OpenCV 的新手,如果我不能正确表达我的问题,我深表歉意。

所以,我有一张我转换为黑白的图像。现在我想将白色像素的所有大块(块可以是任何形状)转换为黑色,并保持小白色像素不变。

为了进一步解释,请看下图: This pic

这是来自另一个 stackoverflow 帖子,但基本上我想要做的是摆脱那个白框,只在我的图片中添加文字。在这张图片中,我可以在顶部放一个黑盒子,因为我知道那个白盒子在哪里,但是当我不知道那个白盒子在哪里时,我该怎么做呢?

提前致谢

编辑:我想要的图片示例是here

【问题讨论】:

  • 什么是小像素?哪个是白色的盒子,里面写的是橙色的?
  • 是的,我基本上是想摆脱那个写着橙色的白盒子。
  • 里面写着橙色,黄色边框也会变成黑色?
  • 我编辑了我的帖子并添加了图片链接。最后链接中的那张图片就是我希望我的代码返回的图片

标签: c++ image opencv computer-vision


【解决方案1】:
  1. 寻找轮廓。
  2. 对于每个轮廓:cv::Rect br = cv::boundingRect(contour)
  3. bwImage(br) = cv::Scalar(0, 0, 0)

【讨论】:

  • 我只想将较大的轮廓转换为黑色。就像上面的图片一样,我只想将那个白框转换为黑色而不是文本。另外,如果形状不是矩形而只是一个随机形状怎么办?
  • 查看br尺寸和尺寸比例
【解决方案2】:

您可以使用minArearect 函数。此函数为每个轮廓绘制拟合矩形。您可以通过设置这些矩形边长进行过滤。

        #include "opencv2/highgui/highgui.hpp"
        #include "opencv2/imgproc/imgproc.hpp"
        #include <iostream>
        #include <stdio.h>
        #include <stdlib.h>

        using namespace cv;
        using namespace std;                        


        int main()
        {

            Mat src; Mat src_gray;
            int thresh = 100;
            RNG rng(12345);
            /// Load source image and convert it to gray
            src = imread( "/ur/src/image_directory/image.png", 1 );
            Mat original = src.clone();
            /// Convert image to gray and blur it
            cvtColor( src, src_gray, CV_BGR2GRAY );
            blur( src_gray, src_gray, Size(3,3) );

            /// Create Window
            char* source_window = "Source";
            namedWindow( source_window, CV_WINDOW_AUTOSIZE );

            Mat threshold_output;
            vector<vector<Point> > contours;
            vector<Vec4i> hierarchy;

            /// Detect edges using Threshold
            threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );
            /// Find contours
            findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

            /// Find the rotated rectangles for each contour
            vector<RotatedRect> minRect( contours.size() );

            for( int i = 0; i < contours.size(); i++ )
                minRect[i] = minAreaRect( Mat(contours[i]) );


            int x1,x2,y1,y2;

            /// Draw contours + rotated rects
            Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
            Mat result_zero = Mat::zeros( threshold_output.size(), CV_8UC3 );

            for( int i = 0; i< contours.size(); i++ )
            {
                Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
                // contour
                drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
                // rotated rectangle
                Point2f rect_points[4]; minRect[i].points( rect_points );

                double length_1 = cv::norm(cv::Mat(rect_points[0]),cv::Mat(rect_points[1]));
                double length_2 = cv::norm(cv::Mat(rect_points[1]),cv::Mat(rect_points[2]));

                //This if scope for your desired rectangle size.You can set your size according to your rectangle(if it changes)
                if(length_1>30 && length_1<100 && length_2>30 && length_2<100)
                {
                    int min_x1 = INT_MAX, max_x2 = 0, min_y1 = INT_MAX, max_y2 = 0;

                    for( int j = 0; j < 4; j++ )
                    {
                        if(rect_points[j].x>max_x2 && rect_points[j].y>max_y2)
                        {
                            max_x2 = rect_points[j].x;
                            max_y2 = rect_points[j].y;
                        }

                        if(rect_points[j].x<min_x1 && rect_points[j].y<min_y1)
                        {
                            min_x1 = rect_points[j].x;
                            min_y1 = rect_points[j].y;

                        }

                        line( result_zero, rect_points[j], rect_points[(j+1)%4], color, 1, 8 );
                    }
                    x1 = min_x1;
                    x2 = max_x2;
                    y1 = min_y1;
                    y2 = max_y2;
                }
            }

            circle(result_zero,Point(x1,y1),3,Scalar(0,255,255),2);
            circle(result_zero,Point(x2,y2),3,Scalar(0,255,255),2);

            // Here in source image we make the rectangle black according to found points
            for(int i=y1-2;i<y2+2;i++)
            {
                for(int j=x1-2;j<x2+2;j++)
                {            
                        src.at<cv::Vec3b>(i,j)[0]=0;
                        src.at<cv::Vec3b>(i,j)[1]=0;
                        src.at<cv::Vec3b>(i,j)[2]=0;            
                }
            }

            /// Show in windows
            namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
            imshow("First",original);
            imshow( source_window, result_zero );
            imshow("Last",src);            
            imshow( "Contours", drawing );                                    
            waitKey(0);
            return(0);
        }

源图片:

积分:

结果:

【讨论】:

  • 如果白色块不是矩形而是像变形虫一样的随机形状物体,这是否有效?
  • @git_status 是的,如果它的拟合矩形长度与上面的矩形相似,它应该可以工作。因为 minAreaRect 刚好适合轮廓。
猜你喜欢
  • 2018-12-23
  • 2019-12-13
  • 1970-01-01
  • 1970-01-01
  • 2018-09-28
  • 1970-01-01
  • 1970-01-01
  • 2021-01-27
  • 2013-09-17
相关资源
最近更新 更多