【问题标题】:opencv - shrink objects to pixelsopencv - 将对象缩小到像素
【发布时间】:2013-07-04 07:09:31
【问题描述】:

我正在处理一个如图1所示的图像,它由一个点数组组成,需要转换为图2。

图1原图


图 2 想要的图片

为了完成转换,我首先检测每个点的edge,然后操作dilation。选择合适的参数后效果令人满意,如图3所示。

图3膨胀后的图像

我之前在 MATLAB 中处理过相同的图像。在将对象(在图 3 中)缩小到像素时,函数 bwmorph(Img,'shrink',Inf) 起作用,结果正是图 2 的来源。那么如何在opencv中获得相同的想要的图像呢?好像没有类似的shrink函数。

这是我查找边缘和膨胀操作的代码:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
using namespace cv;

// Global variables
Mat src, dilation_dst;
int dilation_size = 2;

int main(int argc, char *argv[])
{
    IplImage* img = cvLoadImage("c:\\001a.bmp", 0);                 // 001a.bmp is Fig.1                              

    // Perform canny edge detection
    cvCanny(img, img, 33, 100, 3);

    // IplImage to Mat
    Mat imgMat(img);
    src = img;

    // Create windows
    namedWindow("Dilation Demo", CV_WINDOW_AUTOSIZE);

    Mat element = getStructuringElement(2,                          // dilation_type = MORPH_ELLIPSE
                  Size(2*dilation_size + 1, 2*dilation_size + 1),
                  Point(dilation_size, dilation_size));

    // Apply the dilation operation
    dilate(src, dilation_dst, element);
    imwrite("c:\\001a_dilate.bmp", dilation_dst);
    imshow("Dilation Demo", dilation_dst);

    waitKey(0);
    return 0;
}

【问题讨论】:

    标签: c++ opencv image-processing computer-vision


    【解决方案1】:

    1- Find all the contours 在您的图像中。

    2- 使用moments 找到它们的质心。示例:

    /// Get moments
    vector<Moments> mu(contours.size() );
    for( int i = 0; i < contours.size(); i++ )
    { mu[i] = moments( contours[i], false ); }
    
    /// Get the mass centers:
    vector<Point2f> mc( contours.size() );
    for( int i = 0; i < contours.size(); i++ )
    { mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); }
    

    3- 创建零(黑色)图像并在其上写入所有中心点。

    4- 请注意,您将有额外的一两个点来自边界轮廓。也许您可以根据contour areas 应用一些预过滤,因为边框是一个大面积的连接轮廓。

    【讨论】:

    • 我找到了代码here,但我不明白mc[i] 是什么意思。你能举一个你的步骤3的例子,那就是如何根据mc[i]写点
    • mc 是一个点向量。您应该创建与原始图像相同大小的图像,然后使用 image.at(i,j) = 255; 更改像素;其中 i,j 是取自 mc 的点。请参阅此link。如果不能解决您的问题,请搜索“在 opencv 中更改像素”。
    【解决方案2】:

    它不是很快,但我实现了 William K. Pratt 的 Digital Image Processing, 4th Edition 中的形态过滤算法。这应该正是您正在寻找的。​​p>

    代码已获得 MIT 许可,可在 GitHub 上的 cgmb/shrink 获取。

    具体来说,我已经定义了cv::Mat cgmb::shrink_max(cv::Mat in) 来缩小CV_8UC1 类型的给定cv::Mat,直到无法进一步缩小为止。

    所以,如果我们用您的程序编译 Shrink.cxx 并像这样更改您的代码:

    #include "Shrink.h" // add this line
    ...
    dilate(src, dilation_dst, element);
    dilation_dst = cgmb::shrink_max(dilation_dst); // and this line
    imwrite("c:\\001a_dilate.bmp", dilation_dst);
    

    我们得到这个:

    顺便说一句,您的图片显示了a bug in Octave Image 的 bwmorph 收缩实现。图 2 不应该是图 3 中收缩操作的结果,因为环不应该被收缩操作破坏。如果那个环在 MATLAB 中消失了,它大概也有某种类似的错误。

    目前,Octave 和我从 MATLAB 得到的结果略有不同,但它们非常接近。

    【讨论】:

      猜你喜欢
      • 2018-04-19
      • 2020-07-10
      • 2012-05-23
      • 2021-09-06
      • 1970-01-01
      • 2019-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多