int main()
{
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
int largest_area=0;
int largest_contour_index=0;
OriginalImage = imread("C:\\Data Drive\\opencv Projects\\testwithC++\\Plant001-9\\SideView90\\Day_021.png",CV_LOAD_IMAGE_GRAYSCALE);
BackgroundImage = imread("C:\\Data Drive\\opencv Projects\\testwithC++\\Plant001-9\\SideView90\\Day_001.png",CV_LOAD_IMAGE_GRAYSCALE);
absdiff(OriginalImage,BackgroundImage,GrayImage);
threshold(GrayImage,Binary,80,255,CV_THRESH_BINARY);
namedWindow( "OriginalImage", WINDOW_NORMAL);
imshow("OriginalImage", OriginalImage);
namedWindow( "BackgroundImage", WINDOW_NORMAL);
imshow("BackgroundImage", BackgroundImage);
namedWindow( "GrayImage", WINDOW_NORMAL);
imshow("GrayImage", GrayImage);
namedWindow( "Binary", WINDOW_NORMAL);
imshow("Binary", Binary);
ImageROI = Binary(Rect(300,0,Binary.size().width-600,Binary.size().height));
namedWindow( "ImageROI", WINDOW_NORMAL);
imshow("ImageROI", ImageROI);
dilate(ImageROI,BinaryMorph,Mat(),Point(-1,-1),2);
namedWindow( "BinaryMorph", WINDOW_NORMAL);
imshow("BinaryMorph", BinaryMorph);
findContours(BinaryMorph, contours, hierarchy, RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
for( int i = 0; i< contours.size(); i++ )
{
double a=contourArea(contours[i],false);
if(a>largest_area)
{
largest_area=a;
largest_contour_index=i;
}
}
Contour = Mat(ImageROI.size().width,ImageROI.size().height,CV_8UC1,Scalar::all(0));
drawContours(Contour, contours,largest_contour_index,Scalar(255),CV_FILLED, 8,hierarchy);
vector<Point>hull;
convexHull(contours[largest_contour_index],hull,CV_CLOCKWISE,true);
drawContours(Contour, Mat(hull),largest_contour_index,Scalar(255),3, 8);
namedWindow( "Contour", WINDOW_NORMAL);
imshow("Contour", Contour);
OriginalImage.release();
BackgroundImage.release();
GrayImage.release();
Binary.release();
BinaryMorph.release();
ImageROI.release();
Contour.release();
waitKey(0);
return 0;}
I have written the above code to draw the convex hull of the biggest contour using OpenCV 2.4.9 using microsoft visual studio 2010 express. The code complies and executes without any error, draws the biggest contour successfully, but CANNOT DISPLAY THE CONTOUR.
Please be informed that I used C api so far, and now trying to convert to C++. So, I am new to use openCV with C++. Your advice to make the program work for drawing the convex hull would be greatly appreciated.
The main problem here is that you're calling drawContours
for drawing the convex hull incorrectly.
drawContours accepts as input points a InputArrayOfArrays
, ie a 2 dimensional structure, while hull
is only 1 dimensional.
You can easily fix this creating on the fly a two dimensional vector, with only one element (the hull
), passing as index 0
, ie the first element of the 2D structure you just created:
vector<Point>hull;
convexHull(contours[largest_contour_index], hull, CV_CLOCKWISE, true);
drawContours(Contour, vector<vector<Point>> {hull}, 0, Scalar(128), 3, 8);
or, if C++11 is not available:
vector<Point>hull;
convexHull(contours[largest_contour_index], hull, CV_CLOCKWISE, true);
vector<vector<Point>> tmp;
tmp.push_back(hull);
drawContours(Contour, tmp, 0, Scalar(128), 3, 8);
Also, since you're from a C background, a few tips:
Mat
s, since they are automatically deallocated by their destructor when they go out of scope. Also:
namedWindow
since imshow
will just create that for you. (In the code below I dropped all calls to namedWindow
, but I cannot resize them anymore) CV_8UC1
), you can use the Mat_<Tp>
specialization, ie Mat1b
(aka Mat_<uchar>
). This will produce less verbose code, and also allows you to access elements like mat(i,j)
, instead of mat.at<uchar>(i,j)
(this is not needed here, but just a general advice). dilate
with an empty kernel is useless. Please define a suitable kernel. hierarchy
here, so just don't use it. IMREAD_GRAYSCALE
instead of CV_LOAD_IMAGE_GRAYSCALE
, CHAIN_APPROX_SIMPLE
instead of CV_CHAIN_APPROX_SIMPLE
, etc... imshow
for debugging purposes you can use Image Watch . Here the working code with these tips applied:
#include <opencv2/opencv.hpp>
#include <vector>
#include <string>
using namespace std;
using namespace cv;
int main()
{
// Load images
Mat1b originalImage = imread("path_to_original_image", IMREAD_GRAYSCALE);
Mat1b backgroundImage = imread("path_to_bkg_image", IMREAD_GRAYSCALE);
// Create binary mask
Mat1b grayImage;
absdiff(originalImage, backgroundImage, grayImage);
Mat1b binary;
threshold(grayImage, binary, 80, 255, THRESH_BINARY);
imshow("OriginalImage", originalImage);
imshow("BackgroundImage", backgroundImage);
imshow("GrayImage", grayImage);
imshow("Binary", binary);
// Take a ROI
Rect roi(binary.cols / 3, 0, (binary.cols * 2) / 3, binary.rows);
Mat1b imageROI = binary(roi);
imshow("ImageROI", imageROI);
// Apply morphological dilate, 2 times
Mat1b binaryMorph;
Mat1b kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
dilate(imageROI, binaryMorph, kernel, Point(-1, -1), 2);
imshow("BinaryMorph", binaryMorph);
// Find blob contours
vector<vector<Point>> contours;
double largest_area = 0.0;
int largest_contour_index = 0;
findContours(binaryMorph.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, roi.tl());
if (!contours.empty())
{
// Find largest contour
for (size_t i = 0; i < contours.size(); i++)
{
double a = contourArea(contours[i], false);
if (a > largest_area)
{
largest_area = a;
largest_contour_index = i;
}
}
// Draw largest contors
Mat3b contour(binary.rows, binary.cols, Vec3b(0, 0, 0));
drawContours(contour, contours, largest_contour_index, Scalar(255, 255, 255), CV_FILLED);
// Find convex hull of largest contour
vector<Point>hull;
convexHull(contours[largest_contour_index], hull, CV_CLOCKWISE, true);
// Draw the convex hull
vector<vector<Point>> tmp;
tmp.push_back(hull);
drawContours(contour, tmp, 0, Scalar(0, 0, 255), 3);
imshow("Contour", contour);
}
waitKey(0);
return 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.