Reputation: 23
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
Upvotes: 2
Views: 475
Reputation: 4352
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:
Upvotes: 1
Reputation: 1927
Upvotes: 0