如何检测墙的长边准备面具和重新着色

主要想法是允许用户重新着色到特定的基于墙的用户select。 目前我已经使用cvFloodFill (帮助准备蒙版图像)实现这个function,它可以帮助我改变墙壁的相对HSV值,所以我可以保留边缘。 但是这个解决scheme的问题是,它在颜色上工作,所有的墙壁都被重新绘制,而不是用户select的单个墙壁。

我也尝试canny边缘检测,但它只是能够检测边缘,但不能将其转换为区域。

请find下面的代码,我目前正在使用重绘function

  1. 准备面具

    cvFloodFill(mask, new CvPoint(295, 75), new CvScalar(255, 255, 255,0), cvScalarAll(1), cvScalarAll(1), null, 4, null);

  2. 分裂渠道

    cvSplit(hsvImage, hChannel, sChannel, vChannel, null);

  3. 换颜色

    cvAddS(vChannel, new CvScalar(255*(0.76-0.40),0,0,0), vChannel, mask);

我们如何从图像中检测边缘和相应的区域。

我正在寻找解决scheme,可以不是opencv但应该是可能的iPhone和机器人

示例图像

编辑

使用下面的步骤,我可以实现一些结果

 cvCvtColor(image, gray, CV_BGR2GRAY); cvSmooth(gray,smooth,CV_GAUSSIAN,7,7,0,0); cvCanny(smooth, canny, 10, 250, 5); 

这个输出有两个问题不知道如何解决它们1.靠近边缘2.去除小边缘

在这里输入图像说明

Solutions Collecting From Web of "如何检测墙的长边准备面具和重新着色"

我想我可能有你的解决scheme! 在OpenCV中有一个名为watershed.cpp的示例文件,只需运行它即可得到以下结果:

流域只有短线的关键点

你可以让你的用户在他的屏幕上画出来区分每个墙壁。 那么如果你想要更精确的东西,你可以勾画出这样的区域(不用触及其他线条):

更好的轮廓

和TADA! :

相当不错的结果;)

通过一些工作,你可以使用户友好(取消最后一行,连接区域等)

希望有所帮助!

你可以尝试像这样:

  Mat imageOut = Mat::zeros(imageIn.rows, imageIn.cols, CV_8UC3); vector<vector<Point> > contours; vector<Vec4i> hierarchy; findContours( imageIn, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); for( int idx = 0; idx >= 0; idx = hierarchy[idx][0] ) { Scalar color( rand()&255, rand()&255, rand()&255 ); drawContours( imageOut, contours, idx, color, CV_FILLED, 8, hierarchy ); } 

它应该绘制不同颜色的墙壁。 如果有效,这意味着在“层次结构”中,每个墙都被识别为轮廓,然后您必须找出用户在其触摸屏上select了哪一个,并进行颜色调整处理。

您可能需要在“findContours” 链接中更改不同的参数。 您还需要在轮廓检测之前对input图像进行平滑处理,以避免对细节或纹理感到恼火。

希望有所帮助,托马斯

我想你可以使用Canny Edge Detectionalgorithm来寻找边缘差异。 一些链接

  1. 堆栈溢出
  2. 堆栈溢出
  3. OpenCV QA
  4. OpenCV的
  5. 本机教程

我希望这可以帮助你。 谢谢。

下面是一些OpenCV4Android代码,用于查找Mat称为image的最大轮廓,我们将假定它是在RGBA颜色空间中。 要find轮廓,首先需要对图像进行阈值或二值化(转换为黑白)。 在阈值之前在图像上使用高斯模糊减less了产生的小轮廓的数量。 模糊和阈值的大小参数必须是奇数; 你可以玩耍,find哪个值给出最好的结果(在这里,我已经使用了7)。

 List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Mat BW = new Mat(); Mat hierarchy = new Mat(); MatOfPoint largestContour; Imgproc.cvtColor(image, image, Imgproc.COLOR_RGBA2GRAY); // convert to grayscale Imgproc.GaussianBlur(image, BW, new Size(7,7), 0); Imgproc.adaptiveThreshold(BW, BW, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 7, 2.0); Imgproc.findContours(BW, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); double maxArea = 0; for (MatOfPoint contour : contours) { double area = Imgproc.contourArea(contour); if (area > maxArea) { maxArea = area; largestContour = contour; } } 

这个输出有两个问题不知道如何解决它们1.靠近边缘2.去除小边缘

  1. 您可以使用形态操作来closures边缘。 寻找扩张和closures操作员。

  2. 你可以通过做标签去除小边缘。 计算每个区域的像素数量(连接的白色像素)。 删除任何像素数小于某个阈值的区域。 我不使用opencv,但是大多数库都有一个标签函数,它会创build一个图像,在输出图像中,每一组单色的触摸像素都被分配一个唯一的颜色。