findContours
ブロブ検出に使用します。ここで、近くて類似したブロブを一緒にマージします。
サンプル画像は次のとおりです。
それは通常のOpencvで可能ですか?
findContours
ブロブ検出に使用します。ここで、近くて類似したブロブを一緒にマージします。
サンプル画像は次のとおりです。
それは通常のOpencvで可能ですか?
提供された入力画像は、非常に簡単に操作できます。
最初のステップは、黄色のブロブを他のすべてのものから分離することです。単純なカラー セグメンテーション テクニックでこのタスクを達成できます。色によるセグメンテーションとオブジェクト検出またはOpenCVでの色付きオブジェクトの追跡を見て、その方法を理解することができます。
次に、ブロブをマージします。特に役立つテクニックの 1 つは、すべてのブロブを四角形の中に入れるバウンディング ボックスです。下の画像では、ブロブを囲む緑色の四角形があることに注意してください。
その後、四角形を選択した色で塗りつぶすだけで、すべてのブロブが接続されます。これは最後に宿題として残しておきます。
これは、私が考えることができる最も迅速で最も簡単なアプローチです。次のコードは、今説明したことを実現する方法を示しています。
#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;
}
あなたのプログラムの詳細のおかげで、私はこの解決策を見つけたと思います:(コメントは大歓迎です)
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;
}