You can solve it out by either of the two method explained below.
First method.
Convert to Gray.
Threshold the image.
Find the biggest contour in the threshold image, which will represent boundary of your object.
Find the convexHull of the biggest contour.
Compute the largest rectangle inside the convex polygon. See a good explanation here
Second method.
This one is relatively simple compared to above.
- Convert to Gray.
- Threshold the image
- Find biggest contour to segment object region and draw contour to new Mat.
Apply morphologyEx, here we use morphological Opening . And another thing is that we will use larger kernel size along one direction(x or y) to remove unwanted boarder in your image.
After morphology apply findcontours() and boundingRect() for final segmentation.
Source code
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main(){
//Load image convert to gray scale and threshold
Mat tmp,thr;
Mat src=imread("test.bmp",1);
blur( src, src, Size( 7, 7 ), Point(-1,-1) );
cvtColor(src,tmp,CV_BGR2GRAY);
threshold(tmp,thr,180,255,THRESH_BINARY);
imshow("thr",thr);
//Find biggest contour to segment exact object
vector< vector <Point> > contours; // Vector for storing contour
vector< Vec4i > hierarchy;
int largest_contour_index=0;
int largest_area=0;
Mat dst(src.rows,src.cols,CV_8UC1,Scalar::all(0)); //create destination image
findContours( thr, contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image
for( int i = 0; i< contours.size(); i++ ) // iterate through each contour.
{
double a=contourArea( contours[i],false); // Find the area of contour
if(a>largest_area){
largest_area=a;
largest_contour_index=i; //Store the index of largest contour
}
}
drawContours( dst,contours, largest_contour_index, Scalar(255,255,255),CV_FILLED, 8, hierarchy ); // Draw the largest contour using previously stored index.
imshow("contour",dst);
//Apply morphological opening operation to eliminate unwanted region.
Size kernalSize (7,100); //kernal size may change for differnt image
Mat element = getStructuringElement (MORPH_RECT, kernalSize, Point(1,1) );
morphologyEx( dst, dst, MORPH_OPEN, element );
//find bounding box after morphology.
findContours( dst, contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image always only one contour
Rect rect=boundingRect(contours[0]);
//Crop the rsult
Mat crop=src(rect);
imshow("Cropped",crop);
rectangle( src, rect, Scalar(0,0,255), 1, 8, 0 );
imshow("src",src);
waitKey();
}
Result for sample2.bmp
Size kernalSize (7,100);
Source image
Largest contour
After morphology
Result
And for your first image Sample.bmp you need to change the kernel like
Size kernalSize (100,7);
And here is the result I got with the above kernel
Similar thread can be found here http://answers.opencv.org/question/23910/what-function-will-be-the-best-for-this/#23916 might be helpful.
Hi Haris, Thanks for your reply.
Hi Haris,
May I ask you one thing. My image has 4 borders. So, should I need to iterate 4 times?
I didn’t get your point exactly, and may depend on your algorithm.
Could you please take a look my new image, "sample2.bmp"? According to this image, I need to remove both Left and Right portions. So, I may need to remove 4 sides to get the rectangle. Do you have any better ideal?