我正在尝试使用 floodFill 将我非常缓慢的天真分割重写为更快的东西。一年前我排除了meanShiftFiltering,因为很难标记颜色然后找到它们的轮廓。
当前版本的 opencv 似乎有一个快速的新函数,它使用均值偏移标记段:gpu::meanShiftSegmentation()。它产生如下图像:
(来源:ekran.org)
所以这在我看来非常接近能够生成轮廓。如何运行 findContours 来生成细分?
在我看来,这可以通过从图像中提取标记颜色来完成,然后测试图像中的哪些像素值与每个标签颜色匹配以制作适合 findContours 的布尔图像。这就是我在下面所做的(但它有点慢,让我觉得应该有更好的方法):
Mat image = imread("test.png");
...
// gpu operations on image resulting in gpuOpen
...
// Mean shift
TermCriteria iterations = TermCriteria(CV_TERMCRIT_ITER, 2, 0);
gpu::meanShiftSegmentation(gpuOpen, segments, 10, 20, 300, iterations);
// convert to greyscale (HSV image)
vector<Mat> channels;
split(segments, channels);
// get labels from histogram of image.
int size = 256;
labels = Mat(256, 1, CV_32SC1);
calcHist(&channels.at(2), 1, 0, Mat(), labels, 1, &size, 0);
// Loop through hist bins
for (int i=0; i<256; i++) {
float count = labels.at<float>(i);
// Does this bin represent a label in the image?
if (count > 0) {
// find areas of the image that match this label and findContours on the result.
Mat label = Mat(channels.at(2).rows, channels.at(2).cols, CV_8UC1, Scalar::all(i)); // image filled with label colour.
Mat boolImage = (channels.at(2) == label); // which pixels in labeled image are identical to this label?
vector<vector<Point>> labelContours;
findContours(boolImage, labelContours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
// Loop through contours.
for (int idx = 0; idx < labelContours.size(); idx++) {
// get bounds for this contour.
bounds = boundingRect(labelContours[idx]);
// create ROI for bounds to extract this region
Mat patchROI = image(bounds);
Mat maskROI = boolImage(bounds);
}
}
}
这是最好的方法还是有更好的方法来获取标签颜色?meanShiftSegmentation 提供这些信息似乎是合乎逻辑的?(颜色值向量,或每个标签的掩码向量等)
谢谢你。