Als @Miki bereits erwähnt, können Sie connectedComponents verwenden, um eine Beschriftung durchzuführen. Dann iterieren Sie durch die Begrenzungsbox Ihres Objekts, wie es @Amitay Nachmani vorgeschlagen hat. Aber statt pointPolygonTest die Verwendung können Sie überprüfen, ob der Wert an Ihren aktuellen Positionen entspricht Ihr aktuelles Etikett Hier ist ein kleines Beispiel:
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <vector>
using namespace cv;
using namespace std;
Mat binary, labels, stats, centroids;
int main()
{
Mat src = imread("C:\\Users\\phili\\Pictures\\t06-4.png",0);
threshold(src, binary, 0, 255, CV_THRESH_OTSU);
int nLabels = connectedComponentsWithStats(binary, labels, stats, centroids);
vector<vector<Point>> blobs(nLabels-1);
for (int i = 1; i < nLabels; i++) //0 is background
{
//get bounding rect
int left = stats.at<int>(i, CC_STAT_LEFT) ;
int top = stats.at<int>(i, CC_STAT_TOP);
int width = stats.at<int>(i, CC_STAT_WIDTH);
int height = stats.at<int>(i, CC_STAT_HEIGHT);
blobs[i - 1].reserve(width*height);
int x_end = left + width;
int y_end = top + height;
for (int x = left; x < x_end; x++)
{
for (int y = top; y < y_end; y++)
{
Point p(x, y);
if (i == labels.at<int>(p))
{
blobs[i-1].push_back(p);
}
}
}
}
}
EDIT:
Seit youre OpenCV mit 2.4 gibt es zwei Möglichkeiten, die gleichen Ergebnisse erzielen. Zuerst können Sie findContours verwenden, um die Blobs zu erkennen, und dann in ein neues Bild mit einer bestimmten Farbe als Beschriftung zeichnen (beachten Sie, dass Ihre Blobs Löcher enthalten könnten). Dann durchlaufen Sie das Bild innerhalb des Begrenzungsrechtecks jeder Kontur und Erhalte alle Punkte mit dem Label deiner aktuellen Kontur. Wenn Sie nur das Begrenzungsrechteck in Ihrem Binärbild durchlaufen, haben Sie Probleme mit Objekten, die das Begrenzungsrechteck überlappen. Hier ist der Code:
int getBlobs(Mat binary, vector<vector<Point>> & blobs)
{
Mat labels(src.size(), CV_32S);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(binary, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);
blobs.clear();
blobs.reserve(contours.size());
int count = 1; //0 is background
for (int i = 0; i < contours.size(); i++) // iterate through each contour.
{
//if contour[i] is not a hole
if (hierarchy[i][3] == -1)
{
//draw contour without holes
drawContours(labels, contours, i, Scalar(count),CV_FILLED, 0, hierarchy, 2, Point());
Rect rect = boundingRect(contours[i]);
int left = rect.x;
int top = rect.y;
int width = rect.width;
int height = rect.height;
int x_end = left + width;
int y_end = top + height;
vector<Point> blob;
blob.reserve(width*height);
for (size_t x = left; x < x_end; x++)
{
for (size_t y = top; y < y_end; y++)
{
Point p(x, y);
if (count == labels.at<int>(p))
{
blob.push_back(p);
}
}
}
blobs.push_back(blob);
count++;
}
}
count--;
return count;
}
Zweitens können Sie Ihre eigene Etiketten- mit Floodfill durchführen kann. Daher iterieren Sie durch Ihr Bild und beginnen mit der Überfüllung für jedes weiße Pixel, durchlaufen das umgebende Rechteck und erhalten alle Punkte, die dieselbe seedColor haben. Hier ist der Code:
int labeling(Mat binary, vector<vector<Point>> &blobs)
{
FindBlobs(binary, blobs);
return blobs.size();
}
mit
void FindBlobs(const Mat &binary, vector<vector<Point>> &blobs)
{
blobs.clear();
// Fill the label_image with the blobs
// 0 - background
// 1 - unlabelled foreground
// 2+ - labelled foreground
cv::Mat label_image;
binary.convertTo(label_image, CV_32FC1);
float label_count = 2; // starts at 2 because 0,1 are used already
for (int y = 0; y < label_image.rows; y++) {
float *row = (float*)label_image.ptr(y);
for (int x = 0; x < label_image.cols; x++) {
if (row[x] != 255) {
continue;
}
cv::Rect rect;
cv::floodFill(label_image, Point(x, y), Scalar(label_count), &rect, Scalar(0), Scalar(0), 4);
vector<Point> blob;
blob.reserve(rect.width*rect.height);
for (int i = rect.y; i < (rect.y + rect.height); i++) {
float *row2 = (float*)label_image.ptr(i);
for (int j = rect.x; j < (rect.x + rect.width); j++) {
if (row2[j] != label_count)
{
continue;
}
blob.push_back(Point(j, i));
}
}
blobs.push_back(blob);
label_count++;
}
}
}
ich verwendet, um dieses Bild:
Und hier sind die Begrenzungskästen und die Punkte innerhalb der Kontur für die Visualisierung:
Was genau meinen Sie mit "Finden der Pixel"? Definieren Sie Ihr Problem klarer und veranschaulichen Sie noch besser, was Sie meinen, indem Sie ein Beispiel geben. –
Eigentlich bekomme ich die Pixel der Grenze mit der Funktion findContours(), aber ich bin nicht in der Lage, die Pixel innerhalb der Kontur oder Grenze zu bekommen. Ich muss die Pixel ohne Iteration durch das ganze Bild Pixel finden. – Bloklo
Können Sie 'connectedComponents' überhaupt nicht verwenden? – Miki