gpt4 book ai didi

c++ - 使用OpenCV C++绘制最大轮廓的凸包

转载 作者:太空宇宙 更新时间:2023-11-03 22:00:22 25 4
gpt4 key购买 nike

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

我已经编写了上面的代码,使用 OpenCV 2.4.9 使用 Microsoft Visual Studio 2010 Express 绘制最大轮廓的凸包。代码编译执行无误,成功绘制最大等高线,但无法显示等高线。

请注意,到目前为止我使用的是 C api,现在正在尝试转换为 C++。所以,我不熟悉将 openCV 与 C++ 结合使用。非常感谢您提出建议,使程序能够绘制凸包。

最佳答案

这里的主要问题是您正在调用 drawContours错误地绘制了凸包。

drawContours接受 InputArrayOfArrays 作为输入点,即二维结构,而hull只有一维。

您可以轻松解决此问题,动态创建一个二维 vector ,只有一个元素(hull),作为索引传递 0 ,即您刚刚创建的二维结构的第一个元素:

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 s,因为当它们超出范围时,它们会被析构函数自动释放。

还有:

  • 如果您不需要调整窗口大小,则无需调用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等等……
  • 最好不要在代码中加入魔法值(例如 ROI 值 300、600)。
  • 如果您使用默认值,则无需指定参数。
  • 带有大写字母的名称通常用于类和结构名称,而不是变量(这在某种程度上是主观的,但我个人认为它使代码更易于阅读)。
  • 如果您没有检测到任何轮廓,则跳过计算。
  • 如果您使用的是 VisualStudio,而不是使用所有这些 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;
}

关于c++ - 使用OpenCV C++绘制最大轮廓的凸包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36683556/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com