分水岭算法后边界框和圆圈过多
Having too many bounding boxes and circles after watershed algorithm
我在使用分水岭后找不到边界框和圆圈。我使用 Opencv 2 Computer Vision Application Programming Cookbook 分水岭算法书和 opencv.org 创建边界框和圆圈的示例。
我的问题是我的对象有太多方框和圆圈。另外,为什么要给图片加上边框?
我正在使用 OpenCV 2.4.11 和 Visual Studio Express 2013。
这是我的代码:
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "header.h"
using namespace cv;
using namespace std;
int main()
{
// Read Input Image
Mat src = imread("toy.png");
// Convert the input image to gray-scale
Mat src_gray;
cvtColor(src, src_gray, CV_BGR2GRAY);
// Threshold the gray-input image
Mat src_thresh;
threshold(src_gray, src_thresh, 100, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
// Detect the foreground.
Mat fg;
erode(src_thresh, fg, Mat(), Point(-1, -1), 6);
// Detect the background
Mat bg;
dilate(src_thresh, bg, Mat(), Point(-1, -1), 6);
threshold(bg, bg, 1, 128, THRESH_BINARY_INV);
// Get the markers
Mat markers(src_thresh.size(), CV_8U, Scalar(0));
markers = fg + bg;
// Create watershed segmentation object
WatershedSegmenter segmenter;
// Set markers and process
segmenter.setMarkers(markers);
segmenter.process(src);
// Get segmentation result
Mat seg = segmenter.getSegmentation();
// Get watersheds
Mat ws = segmenter.getWatersheds();
// Display the result
imshow("Watershed", ws);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Find contours
findContours(ws, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
/// Approximate contours to polygons + get bounding rects and circles
vector<vector<Point> > contours_poly(contours.size());
vector<Rect> boundRect(contours.size());
vector<Point2f>center(contours.size());
vector<float>radius(contours.size());
for (int i = 0; i < contours.size(); i++)
{
approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);
boundRect[i] = boundingRect(Mat(contours_poly[i]));
minEnclosingCircle((Mat)contours_poly[i], center[i], radius[i]);
}
/// Draw polygonal contour + bonding rects + circles
Mat drawing = Mat::zeros(ws.size(), CV_8UC3);
for (int i = 0; i< contours.size(); i++)
{
drawContours(drawing, contours_poly, i, Scalar(0, 0, 255), 1, 8, vector<Vec4i>(), 0, Point());
rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), Scalar(255, 0, 0), 2, 8, 0);
circle(drawing, center[i], (int)radius[i], Scalar(0, 255, 0), 2, 8, 0);
}
/// Show in a window
imshow("Contours", drawing);
waitKey();
return 0;
}
这是 header.h 文件:
#if !defined WATERSHS
#define WATERSHS
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
class WatershedSegmenter {
private:
cv::Mat markers;
public:
void setMarkers(const cv::Mat& markerImage) {
// Convert to image of ints
markerImage.convertTo(markers, CV_32S);
}
cv::Mat process(const cv::Mat &image) {
// Apply watershed
cv::watershed(image, markers);
return markers;
}
// Return result in the form of an image
cv::Mat getSegmentation() {
cv::Mat tmp;
// all segment with label higher than 255
// will be assigned value 255
markers.convertTo(tmp, CV_8U);
return tmp;
}
// Return watershed in the form of an image
cv::Mat getWatersheds() {
cv::Mat tmp;
markers.convertTo(tmp, CV_8U, 255, 255);
return tmp;
}
};
#endif
toy.png:
watershed.png:
contours.png:
谢谢。
问题是您向 findContour
传递了一个二值图像,其中边缘(前景)设置为 0
,其余部分(背景)设置为 255
.
findContours
期望前景是 >0
,背景是 0
。所以你需要反转你传递给 findContour
的二值图像,比如:
/// Find contours
Mat ws_negate = ~ws;
findContours(ws_negate, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
结果图像将是:
我在使用分水岭后找不到边界框和圆圈。我使用 Opencv 2 Computer Vision Application Programming Cookbook 分水岭算法书和 opencv.org 创建边界框和圆圈的示例。
我的问题是我的对象有太多方框和圆圈。另外,为什么要给图片加上边框?
我正在使用 OpenCV 2.4.11 和 Visual Studio Express 2013。
这是我的代码:
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "header.h"
using namespace cv;
using namespace std;
int main()
{
// Read Input Image
Mat src = imread("toy.png");
// Convert the input image to gray-scale
Mat src_gray;
cvtColor(src, src_gray, CV_BGR2GRAY);
// Threshold the gray-input image
Mat src_thresh;
threshold(src_gray, src_thresh, 100, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
// Detect the foreground.
Mat fg;
erode(src_thresh, fg, Mat(), Point(-1, -1), 6);
// Detect the background
Mat bg;
dilate(src_thresh, bg, Mat(), Point(-1, -1), 6);
threshold(bg, bg, 1, 128, THRESH_BINARY_INV);
// Get the markers
Mat markers(src_thresh.size(), CV_8U, Scalar(0));
markers = fg + bg;
// Create watershed segmentation object
WatershedSegmenter segmenter;
// Set markers and process
segmenter.setMarkers(markers);
segmenter.process(src);
// Get segmentation result
Mat seg = segmenter.getSegmentation();
// Get watersheds
Mat ws = segmenter.getWatersheds();
// Display the result
imshow("Watershed", ws);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Find contours
findContours(ws, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
/// Approximate contours to polygons + get bounding rects and circles
vector<vector<Point> > contours_poly(contours.size());
vector<Rect> boundRect(contours.size());
vector<Point2f>center(contours.size());
vector<float>radius(contours.size());
for (int i = 0; i < contours.size(); i++)
{
approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);
boundRect[i] = boundingRect(Mat(contours_poly[i]));
minEnclosingCircle((Mat)contours_poly[i], center[i], radius[i]);
}
/// Draw polygonal contour + bonding rects + circles
Mat drawing = Mat::zeros(ws.size(), CV_8UC3);
for (int i = 0; i< contours.size(); i++)
{
drawContours(drawing, contours_poly, i, Scalar(0, 0, 255), 1, 8, vector<Vec4i>(), 0, Point());
rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), Scalar(255, 0, 0), 2, 8, 0);
circle(drawing, center[i], (int)radius[i], Scalar(0, 255, 0), 2, 8, 0);
}
/// Show in a window
imshow("Contours", drawing);
waitKey();
return 0;
}
这是 header.h 文件:
#if !defined WATERSHS
#define WATERSHS
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
class WatershedSegmenter {
private:
cv::Mat markers;
public:
void setMarkers(const cv::Mat& markerImage) {
// Convert to image of ints
markerImage.convertTo(markers, CV_32S);
}
cv::Mat process(const cv::Mat &image) {
// Apply watershed
cv::watershed(image, markers);
return markers;
}
// Return result in the form of an image
cv::Mat getSegmentation() {
cv::Mat tmp;
// all segment with label higher than 255
// will be assigned value 255
markers.convertTo(tmp, CV_8U);
return tmp;
}
// Return watershed in the form of an image
cv::Mat getWatersheds() {
cv::Mat tmp;
markers.convertTo(tmp, CV_8U, 255, 255);
return tmp;
}
};
#endif
toy.png:
watershed.png:
contours.png:
谢谢。
问题是您向 findContour
传递了一个二值图像,其中边缘(前景)设置为 0
,其余部分(背景)设置为 255
.
findContours
期望前景是 >0
,背景是 0
。所以你需要反转你传递给 findContour
的二值图像,比如:
/// Find contours
Mat ws_negate = ~ws;
findContours(ws_negate, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
结果图像将是: