我在代码中遇到了一点。首先简要说明我在做什么:作为输入,有一个地板的图像。使用Canny和HoughLinesP算法,我希望将整个墙分割成许多小的"小"正如你在这里看到的那样,它们同时理想的输出(这里没有canny),我想得到 - 一段在两条红线之间。
好吧,因为我实际上这个outout
我想知道如何合并彼此过于密切的线条。例如,线2,4,3,5,6应该是一条线,也算作一条线。比第7行到第15行也应该是一行,这将是第二行。
当然,我做了一些研究并尝试了这个:
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <experimental/filesystem>
using namespace cv;
using namespace std;
Mat srcReal = //here's this image http://imgur.com/a/Kcjp6
Mat src, dst, cdst;
vector<Vec4i> lines;
void wallMapping(Mat src) {
Scalar mu, sigma;
meanStdDev(src, mu, sigma);
Canny(src, dst, mu.val[0] - sigma.val[0], mu.val[0] + sigma.val[0], 3, false);
cvtColor(dst, cdst, CV_GRAY2BGR);
HoughLinesP(dst, lines, 1, CV_PI / 2, 50, 50, 200);
sort(lines.begin(), lines.end(), vec4iSortByX()); ///sort all lines by number
for (size_t i = 1; i < lines.size(); i++) {
Vec4i current = lines[i]; ///set current lines
Point pt1 = Point(current[0], current[1]);
Point pt2 = Point(current[2], current[3]);
Vec4i previous = lines[i - 1]; ///set previous lines
Point ppt1 = Point(previous[0], previous[1]);
Point ppt2 = Point(previous[2], previous[3]);
int gradient1, gradient2;
if (pt1.x - pt2.x != 0) {
gradient1 = (pt1.y - pt2.y) / (pt1.x - pt2.x);
gradient2 = (ppt1.y - ppt2.y) / (ppt1.x - ppt2.x);
}
Point avrgpt1, avrgpt2;
if (gradient1 == gradient2) {
avrgpt1.x = (pt1.x + ppt1.x) / 2;
avrgpt2.x = (pt2.x + ppt2.x) / 2;
avrgpt1.y = (pt1.y + ppt1.y) / 2;
avrgpt2.y = (pt2.y + ppt2.y) / 2;
}
double angle = atan2(ppt2.y - ppt1.y, ppt2.x - ppt1.x) * 180.0 / CV_PI; ///draw only vertical lines (90 degree)
if (angle) {
std::vector<int> lineLabel;
int numLines = cv::partition(lines, lineLabel, isEqual);
line(cdst, avrgpt1, avrgpt2, Scalar(0, 0, 255), 2, CV_AA);
}
cv::putText(cdst, to_string(i+1), pt2 + Point(0, 10), 4, 1, Scalar(0, 255, 0), 1, 8, false);
//some other stuff
}
//main
int main(int argc, char *argv[]) {
wallMapping(srcReal);
waitKey(0);
return 0;
}
但是当你看上面的图片时,你会发现我在代码中的合并想法并不奏效。因此,我对代码的想法,方法或更正感到高兴!谢谢!
答案 0 :(得分:0)
在单独的二进制图像中绘制线条,在它们上形成形态,使彼此接近的线条合并,然后用一些小内核侵蚀图像,例如: 3x3留下细线。
之后,从您刚刚创建的二进制图像中获取非零坐标,并在所需图像中绘制这些坐标。
为了将这些新线条放回到矢量中,您可以在findContours()
的二进制图像中找到轮廓,然后找到每个轮廓的2个极值点(极值x或y值的点) - 这些是描述这条线的点。