如何在OpenCV for Android中从每个轮廓提取线条?
我想检查每个Canny检测到的边缘,并寻找其中的主线(检查它们是否看起来像一个矩形,例如两对线是否平行等等) Imgproc.HoughLinesP做了我想要的,但它给出了整个图像的线条,我想知道哪些线条来自相同的边缘 我也尝试过寻找轮廓,并用approxPolyDP在每个轮廓中寻找主线,但这看起来并不合适,因为在精明检测到的边缘中经常有间隙。这将提供边的轮廓,而不是边本身 下面是一个测试图像示例:如何在OpenCV for Android中从每个轮廓提取线条?,android,opencv,Android,Opencv,我想检查每个Canny检测到的边缘,并寻找其中的主线(检查它们是否看起来像一个矩形,例如两对线是否平行等等) Imgproc.HoughLinesP做了我想要的,但它给出了整个图像的线条,我想知道哪些线条来自相同的边缘 我也尝试过寻找轮廓,并用approxPolyDP在每个轮廓中寻找主线,但这看起来并不合适,因为在精明检测到的边缘中经常有间隙。这将提供边的轮廓,而不是边本身 下面是一个测试图像示例: 如何为每个形状获取一组线?如果您使用的是OpenCV 3.0.0,则可以使用LineSegm
如何为每个形状获取一组线?如果您使用的是OpenCV 3.0.0,则可以使用
LineSegmentDetector
,以及带有轮廓的“和”检测线
我在下面提供了一个示例代码。它是C++(很抱歉),但是你可以用java轻松翻译。至少您了解了如何使用LineSegmentDetector
以及如何为每个轮廓提取公共线。您将看到同一轮廓上具有相同颜色的线条
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
RNG rng(12345);
Mat3b img = imread("path_to_image");
Mat1b gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
Mat3b result;
cvtColor(gray, result, COLOR_GRAY2BGR);
// Detect lines
Ptr<LineSegmentDetector> detector = createLineSegmentDetector();
vector<Vec4i> lines;
detector->detect(gray, lines);
// Draw lines
Mat1b lineMask(gray.size(), uchar(0));
for (int i = 0; i < lines.size(); ++i)
{
line(lineMask, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), Scalar(255), 2);
}
// Compute edges
Mat1b edges;
Canny(gray, edges, 200, 400);
// Find contours
vector<vector<Point>> contours;
findContours(edges.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
for (int i = 0; i < contours.size(); ++i)
{
// Draw each contour
Mat1b contourMask(gray.size(), uchar(0));
drawContours(contourMask, contours, i, Scalar(255), 2); // Better use 1 here. 2 is just for visualization purposes
// AND the contour and the lines
Mat1b bor;
bitwise_and(contourMask, lineMask, bor);
// Draw the common pixels with a random color
vector<Point> common;
findNonZero(bor, common);
Vec3b color = Vec3b(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
for (int j = 0; j < common.size(); ++j)
{
result(common[j]) = color;
}
}
imshow("result", result);
waitKey();
return 0;
}
#包括
使用名称空间cv;
使用名称空间std;
int main()
{
RNG RNG(12345);
Mat3b img=imread(“路径到图像”);
Mat1b灰色;
CVT颜色(img,灰色,颜色为灰色);
Mat3b结果;
CVT颜色(灰色、结果、颜色_GRAY2BGR);
//探测线
Ptr检测器=createLineSegmentDetector();
矢量线;
检测器->检测(灰色、线条);
//划线
Mat1b线掩码(灰色.size(),uchar(0));
对于(int i=0;i
根据Miki的回答,以下是我所做的:
- 精明的
- HoughLinesP(或LineSegmentDetector,根据需要):检测线
- :在Canny图像中查找Canny“轮廓”
- 使用3x3内核进行扩展(见下文)
- 对于每条Hough线:从该线中选取几个像素并查找最频繁的值(忽略0)。
例如,我选择了
,因此如果我的值是{p1,0.75*p1+0.25*p2,0.5*p1+0.5*p2,0.25*p1+0.75*p2,p2}
,那么该行属于连接组件编号2。 放大是为了确保你没有错过一个轮廓只有1像素(但不要使用它,如果你的对象太近){1,2,0,2,2}
// open image
File root = Environment.getExternalStorageDirectory();
File file = new File(root, "image_test.png");
Mat mRGBA = Imgcodecs.imread(file.getAbsolutePath());
Imgproc.cvtColor(mRGBA, mRGBA, Imgproc.COLOR_BGR2RGB);
Mat mGray = new Mat();
Imgproc.cvtColor(mRGBA, mGray, Imgproc.COLOR_RGBA2GRAY);
Imgproc.medianBlur(mGray, mGray, 7);
/* Main part */
Imgproc.Canny(mGray, mGray, 50, 60, 3, true);
Mat aretes = new Mat();
Imgproc.HoughLinesP(mGray, aretes, 1, 0.01745329251, 30, 10, 4);
/**
* Tag Canny edges in the gray picture with indexes from 1 to 65535 (0 = background)
* (Make sure there are less than 255 components or convert mGray to 16U before)
*/
int nb = Imgproc.connectedComponents(mGray,mGray,8,CvType.CV_16U);
Imgproc.dilate(mGray, mGray, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3,3)));
// for each Hough line
for (int x = 0; x < aretes.rows(); x++) {
double[] vec = aretes.get(x, 0);
double x1 = vec[0],
y1 = vec[1],
x2 = vec[2],
y2 = vec[3];
/**
* Take 5 points from the line
*
* x----x----x----x----x
* P1 P2
*/
double[] pixel_values = new double[5];
pixel_values[0] = mGray.get((int) y1, (int) x1)[0];
pixel_values[1] = mGray.get((int) (y1*0.75 + y2*0.25), (int) (x1*0.75 + x2*0.25))[0];
pixel_values[2] = mGray.get((int) ((y1 + y2) *0.5), (int) ((x1 + x2) *0.5))[0];
pixel_values[3] = mGray.get((int) (y1*0.25 + y2*0.75), (int) (x1*0.25 + x2*0.75))[0];
pixel_values[4] = mGray.get((int) y2, (int) x2)[0];
/**
* Look for the most frequent value
* (To make it readable, the following code accepts the line only if there are at
* least 3 good pixels)
*/
double value;
Arrays.sort(pixel_values);
if (pixel_values[1] == pixel_values[3] || pixel_values[0] == pixel_values[2] || pixel_values[2] == pixel_values[4]) {
value = pixel_values[2];
}
else {
value = 0;
}
/**
* Now value is the index of the connected component (or 0 if it's a bad line)
* You can store it in an other array, here I'll just draw the line with the value
*/
if (value != 0) {
Imgproc.line(mRGBA,new Point(x1,y1),new Point(x2,y2),new Scalar((value * 41 + 50) % 255, (value * 69 + 100) % 255, (value * 91 + 60) % 255),3);
}
}
Imgproc.cvtColor(mRGBA, mRGBA, Imgproc.COLOR_RGB2BGR);
File file2 = new File(root, "image_test_OUT.png");
Imgcodecs.imwrite(file2.getAbsolutePath(), mRGBA);
//打开图像
文件root=Environment.getExternalStorageDirectory();
File File=新文件(根,“image_test.png”);
Mat mRGBA=Imgcodecs.imread(file.getAbsolutePath());
CVT颜色(mRGBA,mRGBA,Imgproc.COLOR_BGR2RGB);
Mat mGray=新Mat();
Imgproc.cvtColor(mRGBA、mGray、Imgproc.COLOR_RGBA2GRAY);
Imgproc.medianBlur(mGray,mGray,7);
/*主体*/
Imgproc.Canny(mGray,mGray,50,60,3,true);
Mat aretes=新Mat();
HoughLinesP(mGray,aretes,1,0.01745329251,30,10,4);
/**
*标记灰色图片中的Canny边缘,索引范围为1到65535(0=背景)
*(请确保组件少于255个,或在之前将mGray转换为16U)
*/
int nb=Imgproc.connectedComponents(mGray,mGray,8,CvType.CV_16U);
Imgproc.deflate(mGray,mGray,Imgproc.getStructuringElement(Imgproc.morp\u RECT,新大小(3,3));
//对于每条Hough线
对于(int x=0;x