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;}
我已经使用microsoft visual studio 2010 express编写了上面的代码,使用OpenCV 2.4.9绘制最大轮廓的凸包。代码符合并执行没有任何错误,成功绘制最大轮廓,但不能显示轮廓。
请注意,到目前为止我使用过C api,现在尝试转换为C ++。所以,我是新手,使用openCV和C ++。你的建议是让程序适用于绘制凸包,我们将非常感激。
答案 0 :(得分:5)
这里的主要问题是你正在调用drawContours
错误地绘制凸包。
drawContours接受InputArrayOfArrays
作为输入点,即2维结构,而hull
仅为1维。
你可以轻松地动态修复这个创建一个二维向量,只有一个元素(hull
),传递为索引0
,即你刚刚创建的2D结构的第一个元素:
vector<Point>hull;
convexHull(contours[largest_contour_index], hull, CV_CLOCKWISE, true);
drawContours(Contour, vector<vector<Point>> {hull}, 0, Scalar(128), 3, 8);
或者,如果C ++ 11不可用:
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);
此外,由于你来自C背景,有一些提示:
Mat
,因为当它们超出范围时,它们会被析构函数自动释放。此外:
namedWindow
,因为imshow
将为您创建。 (在下面的代码中,我删除了对namedWindow
的所有调用,但我不能再调整它们了。)CV_8UC1
),因此您可以使用Mat_<Tp>
专精,即Mat1b
(又名Mat_<uchar>
)。这将产生更简洁的代码,并且还允许您访问mat(i,j)
之类的元素,而不是mat.at<uchar>(i,j)
(这里不需要,但只是一般建议)。dilate
没用。请定义合适的内核。hierarchy
,所以请不要使用它。IMREAD_GRAYSCALE
代替CV_LOAD_IMAGE_GRAYSCALE
,CHAIN_APPROX_SIMPLE
代替CV_CHAIN_APPROX_SIMPLE
等...... imshow
进行调试,则可以使用Image Watch。这里应用了这些提示的工作代码:
#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;
}