假设我们正在处理图像,有没有办法访问轮廓内的像素?OpenCV:如何在C++中找到轮廓内的像素
我已经找到使用函数findContours()的轮廓,甚至找到了时刻,但我无法找到轮廓内的像素。
任何建议都欢迎!
谢谢!
假设我们正在处理图像,有没有办法访问轮廓内的像素?OpenCV:如何在C++中找到轮廓内的像素
我已经找到使用函数findContours()的轮廓,甚至找到了时刻,但我无法找到轮廓内的像素。
任何建议都欢迎!
谢谢!
由于@Miki已经提到您可以使用connectedComponents执行标签。然后,像@Amitay Nachmani建议的那样遍历对象的边界框。但是,而不是使用pointPolygonTest您可以检查是否在您的当前位置值当前的标签一致这里是一个小例子:
#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);
}
}
}
}
}
编辑:
因为你使用的OpenCV的2.4有两种方法达到相同的结果。 首先,您可以使用findContours来检测blob,然后将它们(填充)绘制为具有特定颜色作为标签的新图像(请注意,您的Blob可能包含空洞)然后遍历每个轮廓的边界矩形内的图像,并使用当前轮廓的标签获取所有点。如果只是遍历二进制图像中的边界矩形,则会遇到与边界矩形重叠的对象的问题。 下面是代码:你可以用floodfill执行自己的labling
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;
}
二。因此,您遍历图像并开始对每个白色像素进行填充,遍历边界矩形并获取所有具有相同seedColor的点。 下面是代码:
int labeling(Mat binary, vector<vector<Point>> &blobs)
{
FindBlobs(binary, blobs);
return blobs.size();
}
与
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++;
}
}
}
我用这个形象:
而且这里的边框和轮廓可视化里面的几点:
在轮廓轮廓边界框内的所有像素上使用pointPolygonTest http://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=pointpolygontest#pointpolygontest。
你是什么意思的“寻找像素”?更清楚地定义你的问题,并通过提供一些例子来更好地说明你的意思。 –
实际上,我通过使用函数findContours()获取边界的像素,但我无法获取轮廓或边界内的像素。 我需要找到没有迭代整个图像像素的像素。 – Bloklo
你不能首先使用'connectedComponents'吗? – Miki