如何绘制每个分割对象的轮廓
How to draw contours of each segmented object
我应用分水岭分割来检测触摸物体,这样做效果很好。现在,我想绘制每个对象的轮廓,这样我就可以得到它们的长度、面积、力矩等。但是分割结果中的对象仍然很感人。所以,我没有画出每一个的轮廓。如何绘制每个对象的轮廓?
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("source.png");
// Create binary image from source image
Mat srcGray;
cvtColor(src, srcGray, CV_BGR2GRAY);
Mat srcThresh;
threshold(srcGray, srcThresh, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
// Perform the distance transform algorithm
Mat dist;
distanceTransform(srcThresh, dist, CV_DIST_L2, 3);
// Normalize the distance image for range = {0.0, 1.0}
normalize(dist, dist, 0, 1., NORM_MINMAX);
// Threshold to obtain the peaks
threshold(dist, dist, 0.1, 3.5, CV_THRESH_BINARY);
// Create the CV_8U version of the distance image
Mat dist_8u;
dist.convertTo(dist_8u, CV_8U);
// Find total markers
std::vector<std::vector<Point> > contours;
findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
int ncomp = contours.size();
// Create the marker image for the watershed algorithm
Mat markers = Mat::zeros(dist.size(), CV_32SC1);
// Draw the foreground markers
for (int i = 0; i < ncomp; i++)
drawContours(markers, contours, i, Scalar::all(i + 1), -1);
// Draw the background marker
circle(markers, Point(5, 5), 3, CV_RGB(255, 255, 255), -1);
// Perform the watershed algorithm
watershed(src, markers);
Mat wgResult = (markers.clone()) * 10000;
imshow("Watershed", wgResult);
waitKey(0);
return 0;
}
源图片:
分水岭结果:
有很多方法可以做到这一点。根据当前显示的图像,您可以简单地进行腐蚀和膨胀操作以将它们分开。但是,如果经过面积更大,这将不起作用。
您需要关闭操作:
http://docs.opencv.org/2.4/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html
- 限制它。
- 应用关闭操作。
- 获取轮廓
根据种子,watershed
返回的 markers
矩阵包含分段区域的索引。因此每个 component 将具有相同的种子值。然后,您可以为每个种子创建一个二进制矩阵,如:
Mat1b mask = (markers == seed);
获得每个组件的二进制掩码后,您可以轻松计算其面积、力矩等...
代码:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("D:\SO\img\postit.png");
// Create binary image from source image
Mat srcGray;
cvtColor(src, srcGray, CV_BGR2GRAY);
Mat srcThresh;
threshold(srcGray, srcThresh, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
// Perform the distance transform algorithm
Mat dist;
distanceTransform(srcThresh, dist, CV_DIST_L2, 3);
// Normalize the distance image for range = {0.0, 1.0}
normalize(dist, dist, 0, 1., NORM_MINMAX);
// Threshold to obtain the peaks
threshold(dist, dist, 0.1, 3.5, CV_THRESH_BINARY);
// Create the CV_8U version of the distance image
Mat dist_8u;
dist.convertTo(dist_8u, CV_8U);
// Find total markers
std::vector<std::vector<Point> > contours;
findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
int ncomp = contours.size();
// Create the marker image for the watershed algorithm
Mat markers = Mat::zeros(dist.size(), CV_32SC1);
// Draw the foreground markers
for (int i = 0; i < ncomp; i++)
drawContours(markers, contours, i, Scalar::all(i + 1), -1);
// Draw the background marker
circle(markers, Point(5, 5), 3, CV_RGB(255, 255, 255), -1);
// Perform the watershed algorithm
watershed(src, markers);
for (int seed = 1; seed <= ncomp; ++seed)
{
Mat1b mask = (markers == seed);
// Now you have the mask, you can compute your statistics
imshow("Mask", mask);
waitKey();
}
return 0;
}
我应用分水岭分割来检测触摸物体,这样做效果很好。现在,我想绘制每个对象的轮廓,这样我就可以得到它们的长度、面积、力矩等。但是分割结果中的对象仍然很感人。所以,我没有画出每一个的轮廓。如何绘制每个对象的轮廓?
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("source.png");
// Create binary image from source image
Mat srcGray;
cvtColor(src, srcGray, CV_BGR2GRAY);
Mat srcThresh;
threshold(srcGray, srcThresh, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
// Perform the distance transform algorithm
Mat dist;
distanceTransform(srcThresh, dist, CV_DIST_L2, 3);
// Normalize the distance image for range = {0.0, 1.0}
normalize(dist, dist, 0, 1., NORM_MINMAX);
// Threshold to obtain the peaks
threshold(dist, dist, 0.1, 3.5, CV_THRESH_BINARY);
// Create the CV_8U version of the distance image
Mat dist_8u;
dist.convertTo(dist_8u, CV_8U);
// Find total markers
std::vector<std::vector<Point> > contours;
findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
int ncomp = contours.size();
// Create the marker image for the watershed algorithm
Mat markers = Mat::zeros(dist.size(), CV_32SC1);
// Draw the foreground markers
for (int i = 0; i < ncomp; i++)
drawContours(markers, contours, i, Scalar::all(i + 1), -1);
// Draw the background marker
circle(markers, Point(5, 5), 3, CV_RGB(255, 255, 255), -1);
// Perform the watershed algorithm
watershed(src, markers);
Mat wgResult = (markers.clone()) * 10000;
imshow("Watershed", wgResult);
waitKey(0);
return 0;
}
源图片:
分水岭结果:
有很多方法可以做到这一点。根据当前显示的图像,您可以简单地进行腐蚀和膨胀操作以将它们分开。但是,如果经过面积更大,这将不起作用。
您需要关闭操作: http://docs.opencv.org/2.4/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html
- 限制它。
- 应用关闭操作。
- 获取轮廓
根据种子,watershed
返回的 markers
矩阵包含分段区域的索引。因此每个 component 将具有相同的种子值。然后,您可以为每个种子创建一个二进制矩阵,如:
Mat1b mask = (markers == seed);
获得每个组件的二进制掩码后,您可以轻松计算其面积、力矩等...
代码:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("D:\SO\img\postit.png");
// Create binary image from source image
Mat srcGray;
cvtColor(src, srcGray, CV_BGR2GRAY);
Mat srcThresh;
threshold(srcGray, srcThresh, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
// Perform the distance transform algorithm
Mat dist;
distanceTransform(srcThresh, dist, CV_DIST_L2, 3);
// Normalize the distance image for range = {0.0, 1.0}
normalize(dist, dist, 0, 1., NORM_MINMAX);
// Threshold to obtain the peaks
threshold(dist, dist, 0.1, 3.5, CV_THRESH_BINARY);
// Create the CV_8U version of the distance image
Mat dist_8u;
dist.convertTo(dist_8u, CV_8U);
// Find total markers
std::vector<std::vector<Point> > contours;
findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
int ncomp = contours.size();
// Create the marker image for the watershed algorithm
Mat markers = Mat::zeros(dist.size(), CV_32SC1);
// Draw the foreground markers
for (int i = 0; i < ncomp; i++)
drawContours(markers, contours, i, Scalar::all(i + 1), -1);
// Draw the background marker
circle(markers, Point(5, 5), 3, CV_RGB(255, 255, 255), -1);
// Perform the watershed algorithm
watershed(src, markers);
for (int seed = 1; seed <= ncomp; ++seed)
{
Mat1b mask = (markers == seed);
// Now you have the mask, you can compute your statistics
imshow("Mask", mask);
waitKey();
}
return 0;
}