我的工作基于带有点阵的图像(图1),最终结果如图4所示.我将逐步解释我的工作.

图1原始图像

步骤1:检测每个对象的边缘,包括点和我想要删除的“环”以获得更好的性能.边缘检测的结果如图2所示.我使用Canny边缘探测器,但它对一些浅灰色点不起作用.我的第一个问题是如何关闭点的轮廓并尽可能减少其他噪音?

图2边缘检测

第2步:扩张每个物体.我找不到填补洞的好方法,所以我直接扩张它们.如图3所示,孔看起来太大,其他噪音也是如此.我的第二个问题是如何填充或扩大孔,以使它们以相同/相似的尺寸填充圆圈?

图3扩张

第3步:找到并绘制每个点的质心.如图4所示,由于粗略图像处理,存在“环”的标记,并且一些点以两个白色像素示出.想要的结果应该只显示一个点的点和一个白色像素.

图4:质量中心

这是我的这3个步骤的代码.任何人都可以帮助我的工作做得更好吗?

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

// Global variables
Mat src,edge,dilation;
int dilation_size = 2;

// Function header
void thresh_callback(int,void*);

int main(int argc,char* argv)
{
    IplImage* img = cvLoadImage("c:\\dot1.bmp",0);         // dot1.bmp = fig. 1

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

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

    namedWindow("Step 1: Edge",CV_WINDOW_AUTOSIZE);
    imshow("Step 1: Edge",src);

    // Apply the dilation operation
    Mat element = getStructuringElement(2,Size(2 * dilation_size + 1,2 * dilation_size + 1),Point(dilation_size,dilation_size));     // dilation_type = MORPH_ELLIPSE
    dilate(src,dilation,element);
    // imwrite("c:\\dot1_dilate.bmp",dilation);            

    namedWindow("Step 2: dilation",CV_WINDOW_AUTOSIZE);
    imshow("Step 2: dilation",dilation);

    thresh_callback( 0,0 );

    waitKey(0);
    return 0;
}

/* function thresh_callback */
void thresh_callback(int,void*)
{
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;

    // Find contours
    findContours(dilation,contours,hierarchy,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE,Point(0,0));

    // Get the 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); 
    }

    // Draw mass centers
    Mat drawing = Mat::zeros(dilation.size(),CV_8UC1);
    for( int i = 0; i< contours.size(); i++ ) {
        Scalar color = Scalar(255,255,255);
        line(drawing,mc[i],color,1,8,0);
    }

    namedWindow("Step 3: Mass Centers",CV_WINDOW_AUTOSIZE);
    imshow("Step 3: Mass Centers",drawing);
}

解决方法

您可以采取一些措施来改善结果.要减少图像中的噪点,可以在应用Canny运算符之前应用中值模糊.这是一种常见的去噪技术.另外,尽量避免使用C API和IplImage.
cv::Mat img = cv::imread("c:\\dot1.bmp",0);         // dot1.bmp = fig. 1

    cv::medianBlur(img,7);

    // Perform canny edge detection
    cv::Canny(img,100);

这可以显着减少边缘图像中的噪声量:

为了更好地保留点的原始大小,您可以使用较小的内核而不是扩张来执行一些形态学闭合迭代.这也会减少点与圆的连接:

// This replaces the call to dilate()
cv::morphologyEx(src,MORPH_CLOSE,cv::noArray(),cv::Point(-1,-1),2);

这将使用3×3内核执行两次迭代,使用cv :: noArray()表示.

结果更清晰,点完全填满:

保持管道的其余部分不被修改会产生最终结果.圆圈中仍有一些虚假的质量中心,但比原始方法少得多:

如果您想尝试完全从结果中删除圆圈,可以尝试使用cv::HoughCircles()并调整参数,直到获得良好的结果.这可能会有一些困难,因为整个圆圈在图像中不可见,只有细分,但我建议你试一试.如果您确实检测到最里面的圆圈,则可以将其用作遮罩来过滤掉外部质量中心.

c – Opencv:边缘检测,膨胀和质量绘图的更多相关文章

  1. python数字图像处理之边缘轮廓检测

    这篇文章主要介绍了python数字图像处理之边缘轮廓检测示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  2. 详解Python中图像边缘检测算法的实现

    这篇文章主要为大家详细介绍了python中图像边缘检测算法的原理及实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. 在PHP中创建基于边缘检测的图像

    我很好奇–有可能在PHP中使用:1)将图像文件发送到服务器2)过程图像=检测边缘并基于边缘创建简单的笔划3)将文件保存在服务器上/发送到用户的浏览器/等等这是一些“样本”文件;P(你可以看到它不是使用任何边缘检测启用的程序,而是手工–只是作为一个例子):http://i51.tinypic.com/5vzo0x.jpg谢谢!如果你可以使用ImageMagick,那就是--charcoalfilte

  4. java – 使用Processing的Canny边缘检测

    解决方法我想如果你用Java处理处理,那么一些问题可以很容易地解决.这意味着您可以使用java类.对于演示,我使用的是您共享的implementation.>>原始图片>>更改了图片>>代码

  5. c – 在OpenCV中边缘检测后找到最佳感兴趣区域

    我想将OCR应用到墙上的7段显示器的一些照片.我的策略如下:>隐藏图像灰度>模糊img减少假边将img限制为二进制img>应用CannyEdge检测>根据数字轮廓给出的模式设置感兴趣区域>缩放ROI和模板匹配区域如何设置投资回报率,使我的程序不必在整个图像中查找模板?

  6. c – Opencv:边缘检测,膨胀和质量绘图

    我的工作基于带有点阵的图像(图1),最终结果如图4所示.我将逐步解释我的工作.图1原始图像步骤1:检测每个对象的边缘,包括点和我想要删除的“环”以获得更好的性能.边缘检测的结果如图2所示.我使用Canny边缘探测器,但它对一些浅灰色点不起作用.我的第一个问题是如何关闭点的轮廓并尽可能减少其他噪音?

  7. Cocos3.4 横版游戏制作-《KillBear》-边缘检测 地图滚动

    上一篇:Cocos3.4横版游戏制作-《KillBear》-添加摇杆并控制Hero上一篇中,我们实现了通过不同层的Joystick控制Hero移动,但是Hero到处跑,还是不能实现我们的效果.此篇上半部分,限定Hero的移动范围是他不要跑出地图或者是墙上下半部分,通过更新MapLayer实现地图滚动效果.开发环境win64:vs2010Cocos2d-xv3.4FinalTexturePackerGUIMapEdit代码构建A角色RoleHero为什么我会在updateSelf中重复写了好几个坐标但是就用

  8. Cocos2d-x地图随精灵无限滚动与边缘检测----之游戏开发《赵云要格斗》3 cocos2dx 3.3移植版

    并且,当地图移动到边缘时,地图不在移动,但此时精灵能移动同时播放跑动画。cocos2d-x版本:2.2.5工程环境:windows7+VS2010打开方式:将工程放在cocos2d-x安装目录下的project文件夹下用VS打开源码免费下载目录一、在英雄类中增加判断英雄是否运动到了窗口的中间位置函数二、自定义地图类三、根据英雄精灵和窗口的大小来移动地图或移动精灵四、思路总结下面是要滚动的地图,只有一张,但是很长。

  9. Cocos2d-x地图随精灵无限滚动与边缘检测----之游戏开发《赵云要格斗》3

    先看看效果一、在英雄类中增加判断英雄是否运动到了窗口的中间位置函数在上一篇的英雄类中再增加一个函数:然后这是它的实现:二、自定义地图类这里为了后头地图能再实现其它功能,我自己又设计了一个地图类,它能根据英雄的运动还判断是否要移动地图其实这里的地图就是一个CCSprite,然后把它加到当前类中,这个类是从CCNODE中派生的。

随机推荐

  1. 从C到C#的zlib(如何将byte []转换为流并将流转换为byte [])

    我的任务是使用zlib解压缩数据包(已接收),然后使用算法从数据中生成图片好消息是我在C中有代码,但任务是在C#中完成C我正在尝试使用zlib.NET,但所有演示都有该代码进行解压缩(C#)我的问题:我不想在解压缩后保存文件,因为我必须使用C代码中显示的算法.如何将byte[]数组转换为类似于C#zlib代码中的流来解压缩数据然后如何将流转换回字节数组?

  2. 为什么C标准使用不确定的变量未定义?

    垃圾价值存储在哪里,为什么目的?解决方法由于效率原因,C选择不将变量初始化为某些自动值.为了初始化这些数据,必须添加指令.以下是一个例子:产生:虽然这段代码:产生:你可以看到,一个完整的额外的指令用来移动1到x.这对于嵌入式系统来说至关重要.

  3. 如何使用命名管道从c调用WCF方法?

    更新:通过协议here,我无法弄清楚未知的信封记录.我在网上找不到任何例子.原版的:我有以下WCF服务我输出添加5行,所以我知道服务器是否处理了请求与否.我有一个.NET客户端,我曾经测试这一切,一切正常工作预期.现在我想为这个做一个非托管的C客户端.我想出了如何得到管道的名称,并写信给它.我从here下载了协议我可以写信给管道,但我看不懂.每当我尝试读取它,我得到一个ERROR_broKEN_P

  4. “这”是否保证指向C中的对象的开始?

    我想使用fwrite将一个对象写入顺序文件.班级就像当我将一个对象写入文件时.我正在游荡,我可以使用fwrite(this,sizeof(int),2,fo)写入前两个整数.问题是:这是否保证指向对象数据的开始,即使对象的最开始可能存在虚拟表.所以上面的操作是安全的.解决方法这提供了对象的地址,这不一定是第一个成员的地址.唯一的例外是所谓的标准布局类型.从C11标准:(9.2/20)Apointe

  5. c – 编译单元之间共享的全局const对象

    当我声明并初始化一个const对象时.两个cpp文件包含此标头.和当我构建解决方案时,没有链接错误,你会得到什么如果g_Const是一个非const基本类型!PrintInUnit1()和PrintInUnit2()表明在两个编译单元中有两个独立的“g_Const”具有不同的地址,为什么?

  6. 什么是C名称查找在这里? (&amp;GCC对吗?)

    为什么在第三个变体找到func,但是在实例化的时候,原始变体中不合格查找找不到func?解决方法一般规则是,任何不在模板定义上下文中的内容只能通过ADL来获取.换句话说,正常的不合格查找仅在模板定义上下文中执行.因为在定义中间语句时没有声明func,并且func不在与ns::type相关联的命名空间中,所以代码形式不正确.

  7. c – 在输出参数中使用auto

    有没有办法在这种情况下使用auto关键字:当然,不可能知道什么类型的.因此,解决方案应该是以某种方式将它们合并为一个句子.这可用吗?解决方法看起来您希望默认初始化给定函数期望作为参数的类型的对象.您无法使用auto执行此操作,但您可以编写一个特征来提取函数所需的类型,然后使用它来声明您的变量:然后你就像这样使用它:当然,只要你重载函数,这一切都会失败.

  8. 在C中说“推动一切浮动”的确定性方式

    鉴于我更喜欢将程序中的数字保留为int或任何内容,那么使用这些数字的浮点数等效的任意算术最方便的方法是什么?说,我有我想写通过将转换放在解析的运算符树叶中,无需将表达式转化为混乱是否可以使用C风格的宏?应该用新的类和重载操作符完成吗?解决方法这是一个非常复杂的表达.更好地给它一个名字:现在当您使用整数参数调用它时,由于参数的类型为double,因此使用常规的算术转换将参数转换为double用C11lambda……

  9. objective-c – 如何获取未知大小的NSArray的第一个X元素?

    在objectiveC中,我有一个NSArray,我们称之为NSArray*largeArray,我想要获得一个新的NSArray*smallArray,只有第一个x对象…

  10. c – Setprecision是混乱

    我只是想问一下setprecision,因为我有点困惑.这里是代码:其中x=以下:方程的左边是x的值.1.105=1.10应为1.111.115=1.11应为1.121.125=1.12应为1.131.135=1.14是正确的1.145=1.15也正确但如果x是:2.115=2.12是正确的2.125=2.12应为2.13所以为什么在一定的价值是正确的,但有时是错误的?请启发我谢谢解决方法没有理由期望使用浮点系统可以正确地表示您的帖子中的任何常量.因此,一旦将它们存储在一个双变量中,那么你所拥有的确切的一

返回
顶部