17

主要思想是允许用户重新着色到基于特定墙壁的用户选择。目前我已经使用cvFloodFill(帮助准备蒙版图像)实现了这个功能,它可以帮助我改变HSV墙的相对值,这样我就可以保留边缘。但这个解决方案的问题是它适用于颜色并且所有墙壁都被重新粉刷而不是用户选择的单一墙壁。

我也尝试过精明的边缘检测,但它只能检测边缘但无法将其转换为区域。

请在下面找到我目前用于重绘功能的代码

  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);

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

我正在寻找可以不是opencv但应该适用于 iPhone 和 android的解决方案

示例图像

编辑

我可以使用以下步骤获得如下图所示的结果

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

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

在此处输入图像描述

4

5 回答 5

10

你可以尝试类似的东西:

 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 );
 }

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

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

希望有帮助,托马斯

于 2013-04-24T14:03:05.083 回答
9

我想我可能会为您提供解决方案!在 OpenCV 中有一个名为 watershed.cpp 的示例文件,只需运行它,您将得到以下结果:

只有短线关键点的分水岭

您可以让您的用户在他的屏幕上绘图以区分每面墙。然后,如果你想要更精确的东西,你可以像这样勾勒出这些区域(不接触其他线条):

更好的轮廓

还有多田!:

相当不错的结果;)

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

希望有帮助!

于 2013-06-27T15:25:58.367 回答
3

我认为您可以使用Canny Edge Detection算法来查找边缘差异。一些链接

  1. 堆栈溢出
  2. 堆栈溢出
  3. OpenCV 质量保证
  4. 开放式CV
  5. 本机教程

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

于 2013-04-24T04:40:55.537 回答
2

这是一些 OpenCV4Android 代码,用于查找被Mat调用的最大轮廓image,我们假设它在 RGBA 颜色空间中。要找到轮廓,首先需要对图像进行阈值化或二值化(转换为黑白)。在阈值化之前在图像上使用高斯模糊可以减少产生的小轮廓的数量。模糊和阈值的大小参数必须是奇数;您可以四处寻找哪个值可以提供最佳结果(在这里,我对两者都使用了 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;
    }
}
于 2013-04-25T03:46:14.370 回答
0

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

  1. 您可以使用形态学操作来关闭边缘。寻找膨胀和闭合运算符。

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

于 2013-04-27T04:04:27.007 回答