简体   繁体   中英

OpenCV C++: Convert big block of white pixels to black

I am new to OpenCV, so apologies if I am not able to express my issue properly.

So, I have an image that I converted to B&W. Now I want to convert all big block (block could be of any shapes) of white pixels to black and leave the small white pixels as it is.

To further explain, please look at the picture below: This pic

This is from another stackoverflow post but basically what I want to do is get rid of that white box and just have text in my picture. In this picture, I can just put a black box on the top since I know where that white box is but how can I do it when I don't know where that white box is?

Thanks in advance

Edit: An example of a picture that I want is here

You can use minArearect function. This function draws fitted rectangles for each contour. You can filter by setting these rectangle edge lengths.

        #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);
        }

Source image:

在此处输入图片说明

Points:

在此处输入图片说明

Result:

在此处输入图片说明

  1. Find contours.
  2. For each contour: cv::Rect br = cv::boundingRect(contour)
  3. bwImage(br) = cv::Scalar(0, 0, 0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM