C++ 如何合并斑点/轮廓
我使用C++ 如何合并斑点/轮廓,c++,opencv,image-processing,C++,Opencv,Image Processing,我使用findContours进行斑点检测。现在,我将把相近的斑点和类似的斑点合并在一起 以下是一些示例图像: 正常的Opencv是否可以这样做?您提供给我们的输入图像非常容易处理: 第一步是将黄色斑点从其他所有斑点中分离出来,一种简单的颜色分割技术可以完成这项任务。你可以看看或有一个如何做的想法 然后,是时候合并BLOB了。一种特别有用的技术是,将所有斑点放入一个矩形中。请注意,在下图中,水滴周围有一个绿色矩形: 在这之后,您所需要做的就是用您选择的颜色填充矩形,从而连接所有的blob
findContours
进行斑点检测。现在,我将把相近的斑点和类似的斑点合并在一起
以下是一些示例图像:
正常的Opencv是否可以这样做?您提供给我们的输入图像非常容易处理: 第一步是将黄色斑点从其他所有斑点中分离出来,一种简单的颜色分割技术可以完成这项任务。你可以看看或有一个如何做的想法 然后,是时候合并BLOB了。一种特别有用的技术是,将所有斑点放入一个矩形中。请注意,在下图中,水滴周围有一个绿色矩形: 在这之后,您所需要做的就是用您选择的颜色填充矩形,从而连接所有的blob。我把最后一个留给你做家庭作业 这是我能想到的最快、最简单的方法。下面的代码演示了如何实现我刚才描述的功能:
#include <cv.h>
#include <highgui.h>
#include <iostream>
#include <vector>
int main(int argc, char* argv[])
{
cv::Mat img = cv::imread(argv[1]);
if (!img.data)
{
std::cout "!!! Failed to open file: " << argv[1] << std::endl;
return 0;
}
// Convert RGB Mat into HSV color space
cv::Mat hsv;
cv::cvtColor(img, hsv, CV_BGR2HSV);
// Split HSV Mat into HSV components
std::vector<cv::Mat> v;
cv::split(hsv,v);
// Erase pixels with low saturation
int min_sat = 70;
cv::threshold(v[1], v[1], min_sat, 255, cv::THRESH_BINARY);
/* Work with the saturated image from now on */
// Erode could provide some enhancement, but I'm not sure.
// cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
// cv::erode(v[1], v[1], element);
// Store the set of points in the image before assembling the bounding box
std::vector<cv::Point> points;
cv::Mat_<uchar>::iterator it = v[1].begin<uchar>();
cv::Mat_<uchar>::iterator end = v[1].end<uchar>();
for (; it != end; ++it)
{
if (*it) points.push_back(it.pos());
}
// Compute minimal bounding box
cv::RotatedRect box = cv::minAreaRect(cv::Mat(points));
// Display bounding box on the original image
cv::Point2f vertices[4];
box.points(vertices);
for (int i = 0; i < 4; ++i)
{
cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 1, CV_AA);
}
cv::imshow("box", img);
//cv::imwrite(argv[2], img);
cvWaitKey(0);
return 0;
}
#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
cv::Mat img=cv::imread(argv[1]);
如果(!img.data)
{
std::cout“!!!无法打开文件:“我想我做到了,多亏了您的程序详细信息,我找到了此解决方案:(欢迎评论)
矢量轮廓;
矢量tmp_等值线;
查找孔(检测到的IMG、tmp轮廓、CV\u RETR\u外部、CV\u链\u近似\u简单);
向量::迭代器it1;
it1=tmp_等高线。开始();
垫试验;
试验=垫(图尺寸(),CV_32FC3);
while(it1!=tmp_等高线.end()){
向量逼近1;
近似聚合(Mat(*it1),近似1,3,真);
Rect box1=边界Rect(近似X1);
浮动面积1=轮廓面积(近似x1);
如果((区域1>50)和&(区域1<13000)和&(框1.宽度<100)和&(框1.高度<120)){
向量::迭代器it2;
it2=tmp_等高线。开始();
while(it2!=tmp_等高线.end()){
向量逼近2;
approxPolyDP(Mat(*it2),approx2,3,真);
力矩m1=力矩(材料(近似值X1),假);
力矩m2=力矩(材料(近似值),假);
浮动x1=m1.m10/m1.m00;
浮动y1=m1.m01/m1.m00;
浮球x2=m2.m10/m2.m00;
浮动y2=m2.m01/m2.m00;
向量距离;
距离推回(点(x1,y1));
距离推回(点(x2,y2));
浮动d=弧长(距离,假);
Rect box2=边界Rect(近似值为x2);
如果(框1!=框2){
如果(d<25){
//方法合并向量
approx1=合并点(approx1,approx2);
}
}
++it2;
}
Rect b=边界Rect(近似值1);
矩形(测试,b,CV_RGB(125,255,0),2);
轮廓。推回(近似X1);
}
++it1;
}
如果您添加一个图像,效果会更好。上传到imageshack.us并在此处提供链接。同时指定“相似”是什么意思。形状相似吗?或面积相似吗?etcok我希望合并相邻的相似形状。以下是三个示例(标记为黄色)谢谢你的帮助!那些二值图像都是经过形态学开闭运算的。所以,基本上你是在找到每个斑点之间的距离,如果距离d小于25,就合并它。但是仍然存在一个问题,如何处理新合并的斑点?因为如果一个斑点合并两个,第三个斑点也应该合并…谢谢你的回答…但是你误解了我一点。黄色的斑点不是真正的黄色。我只是给它们上色,告诉你我会尝试合并的女巫斑点。所以我无法使用颜色分割来隔离其他斑点。还有像区域这样的信息也不起作用,因为可能还有一些更大的斑点我不喜欢合并…呸!=\will稍后再考虑其他问题。不,我只对那些可能是从那里发出的交通信号大小/比率/面积感兴趣。你必须在你的问题中提供尽可能多的细节,否则我们将在黑暗中拍摄。这是一个复杂的问题!如果你不分享你迄今为止所做的尝试,你可能不会得到任何答案。让我告诉你不是这样的:从你给我们的图像中,你怎么知道哪个斑点是交通标志?在我看来,它们是这些图像中最大的斑点听起来很合乎逻辑。我错了吗?
vector<vector<Point> > contours;
vector<vector<Point> > tmp_contours;
findContours(detectedImg, tmp_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
vector<vector<Point> >::iterator it1;
it1 = tmp_contours.begin();
Mat test;
test = Mat(FImage.size(), CV_32FC3);
while (it1 != tmp_contours.end()) {
vector<Point> approx1;
approxPolyDP(Mat(*it1), approx1, 3, true);
Rect box1 = boundingRect(approx1);
float area1 = contourArea(approx1);
if ((area1 > 50) && (area1 < 13000) && (box1.width < 100) && (box1.height < 120)) {
vector<vector<Point> >::iterator it2;
it2 = tmp_contours.begin();
while (it2 != tmp_contours.end()) {
vector<Point> approx2;
approxPolyDP(Mat(*it2), approx2, 3, true);
Moments m1 = moments(Mat(approx1), false);
Moments m2 = moments(Mat(approx2), false);
float x1 = m1.m10 / m1.m00;
float y1 = m1.m01 / m1.m00;
float x2 = m2.m10 / m2.m00;
float y2 = m2.m01 / m2.m00;
vector<Point> dist;
dist.push_back(Point(x1, y1));
dist.push_back(Point(x2, y2));
float d = arcLength(dist, false);
Rect box2 = boundingRect(approx2);
if (box1 != box2) {
if (d < 25) {
//Method to merge the vectors
approx1 = mergePoints(approx1, approx2);
}
}
++it2;
}
Rect b = boundingRect(approx1);
rectangle(test, b, CV_RGB(125, 255, 0), 2);
contours.push_back(approx1);
}
++it1;
}