热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

边缘检索与区域提取

边缘检索与区域提取是我们的课程设计的一个课题。看到这个课题感到十分新颖,因为以前从未接触过这方面的知识。而且由于课程作业要求的语言是c++,所以选择了c++的一个界面类函数库eas

边缘检索与区域提取是我们的课程设计的一个课题。看到这个课题感到十分新颖,因为以前从未接触过这方面的知识。而且由于课程作业要求的语言是c++,所以选择了 c++ 的一个界面类函数库easyX  下载可见官网 http://www.easyx.cn/    我们将这个课题分为两部分,一是边缘检测,一是区域提取。 
   关于边缘检测:图像的边缘形成的原因是图像的灰度在某一区域的突然变化使得人眼才有了识别轮廓的功能。所以对于计算机识别边缘我们也可以用数学的方法定量的找出图像中灰度阶跃不连续或是线条不连续的地方,比如说一阶导数的极值点或二阶导数的零点的方法找到边缘。(图片摘自百度)。 


 

当我们继续往下学时,越来越多的概念涌了出来,各种算子、幅度、差分、阈值、卷积运算。这对我这种数学渣渣的确是一种考验。其实我们没必要将边缘检索的数学推导都看懂。我们只要了解它的基本原理后,在运用它的结论就足以达到我们的目的。 
我们总结了一下:什么Prewitt算子、Sobel算子,都是对灰度图片的一个变换,我们称这个变换为卷积模板变换,模板变换后,边缘就会被检索出来。首先让我们必须了解什么叫做卷积模板变换。这个博客说的很清楚,大家可以看看。 
http://www.cnblogs.com/a-toad/archive/2008/10/24/1318921.html 


所以我们根据这个运算规则,将它封装成一个方法,代码及注释如下 


C++代码  



  1. //模板操作,包括图像边缘的检测,图像的平滑都会用到这个函数  

  2. /*参数的意义 

  3. * img 指向图像的指针 

  4. * tempWidth tempHeight 模板的宽高 

  5. * tempX tempY 模板的中心的x y 坐标 

  6. * temp 指向模板数组的指针 tempCoef 模板的系数 

  7. * img2 为转化后的照片 

  8. */  

  9. bool templateChange(IMAGE *img,int tempWidth,int tempHeight,int tempX,int tempY,float *temp,float tempCoef,IMAGE *img2){  

  10.     long imgWidth = img->getwidth();  

  11.     long imgHeight = img->getheight();  

  12.     //得到原图的内容  

  13.     DWORD *p = GetImageBuffer(img);  

  14.     (*img2).Resize(imgWidth,imgHeight);  

  15.     DWORD *p2 = GetImageBuffer(img2);  

  16.     //用于暂存模板值  

  17.     float result;  

  18.     int endResult;  

  19.     for (long i=tempY;i

  20.         for (long j=tempX;j

  21.             result=0;  

  22.             //计算模板  

  23.             for (int k=0;k

  24.                 for (int l=0;l

  25.                       //逻辑表达式较复杂(横坐标 i-tempy+k 纵坐标 j-tempx+1)  

  26.                     //得到灰度(RGB相同)  

  27.                     int z=GetRValue(p[imgWidth*(i+tempY-k)+j-tempX+l]);  

  28.                     result +=z*temp[k*tempWidth+l];  

  29.                 }  

  30.             }  

  31.             result *=tempCoef;  

  32.             endResult =abs((int)result);  

  33.             if (endResult>255){  

  34.                 endResult=255;  

  35.             }  

  36.             p2[i*imgWidth+j]=RGB(endResult,endResult,endResult);  

  37.         }  

  38.     }  

  39.     return true;  

  40. }  


了解了这个模板运算,我们反过头来再看各种算子 

Sobel算子: 

 

进行的横竖两个方向的模板运算后,遍历整个图片取相同像素点模板运算的最大值。 
Prewitt算子: 

 

同Sobel算子,进行的横竖两个方向的模板运算后,遍历整个图片取相同像素点模板运算的最大值。 

给出了算法,写程序就很容易了。这里只展示prewitt算子的代码: 


C++代码  



  1. void GraphicCut(IMAGE *img){  

  2.     IMAGE img1,img2;  

  3.     float temp1[9]={1,0,-1,1,0,-1,1,0,-1};  

  4.     float tempCoef1=1;  

  5.     templateChange(img,3,3,1,1,temp1,tempCoef1,&img1);  

  6.     float temp2[9]={-1,-1,-1,0,0,0,1,1,1};  

  7.     float tempCoef2=1;  

  8.     templateChange(img,3,3,1,1,temp2,tempCoef2,&img2);  

  9.     DWORD *p = GetImageBuffer(img);  

  10.     DWORD *p1 = GetImageBuffer(&img1);  

  11.     DWORD *p2 = GetImageBuffer(&img2);  

  12.     for (long i=0;igetheight();i++)  

  13.         for (long j=0;jgetwidth();j++)  

  14.             if (p1[i*img->getwidth()+j]

    getwidth()+j]){  


  15.                p[i*img->getwidth()+j]=p2[i*img->getwidth()+j];  

  16.             }else{  

  17.                p[i*img->getwidth()+j]=p1[i*img->getwidth()+j];  

  18.             }  

  19. }  


效果图如下: 

 

 


啃完了边缘检索这块硬骨头后,我们又开始考虑区域要怎么提取。我们最初的想法是做一个类似于搜索的算法,遍历某个区域中的所有点,将这个区域中的像素点提取出来保存到另一幅图片中,就完成了区域提取。 
我们最开始想到的是深度搜索,但对于一张500*500的图片来说,这种搜索对时间和空间的消耗都是特别大的,搞不好还会栈溢出。所以我们马上丢弃了这个想法。另一种搜索方法就是广度搜索了,理论上是可行的,所以我们决定试试这种算法。(其实网上有一些经过优化过的搜索算法,如扫描线算法)。 
代码如下: 


C++代码  



  1. void graphicsFill(IMAGE *img1,IMAGE *img2,IMAGE *img3,int mouseX,int mouseY){  

  2.     long imgWidth = img1->getwidth();  

  3.     long imgHeight = img1->getheight();  

  4.     DWORD *p1 = GetImageBuffer(img1);  

  5.     DWORD *p2 = GetImageBuffer(img2);  

  6.     DWORD *p3 = GetImageBuffer(img3);  

  7.     list

     stk;  


  8.     Point point;  

  9.     point.x = mouseX;  

  10.     point.y = mouseY;  

  11.     stk.push_back(point);  

  12.     int a[]={0,1,1,1,0,-1,-1,-1};  

  13.     int b[]={1,1,0,-1,-1,-1,0,1};  

  14.     while (!stk.empty()){  

  15.         Point pt;  

  16.         //获取链表头元素 ,并将其弹出  

  17.         pt=stk.front();  stk.pop_front();  

  18.         long y=pt.y;  

  19.         long x=pt.x;  

  20.         long z;  

  21.         int x1,y1;  

  22.         for (int i=0;i<8;i++){  

  23.             x1=x+a[i]; y1=y+b[i];  

  24.             z=abs(long(GetRValue(p1[y*imgWidth+x])-GetRValue(p1[y1*imgWidth+x1])));  

  25.             if (p2[y1*imgWidth+x1]!=p3[y1*imgWidth+x1]&&z<4){  

  26.                p3[y1*imgWidth+x1]=p2[y1*imgWidth+x1];  

  27.                Point pt;  

  28.                pt.x=x1; pt.y=y1;  

  29.                stk.push_back(pt);  

  30.             }  

  31.         }  

  32.     }  

  33. }  


提取效果图片如下: 

 


 


 


整的来说,算法的效率还算高。但的确有更好的算法可以去解决这个问题,更好的算法就等读者自己去研究发现了。



推荐阅读
  • 来自FallDream的博客,未经允许,请勿转载,谢谢。一天一套noi简直了.昨天勉强做完了noi2011今天教练又丢出来一套noi ... [详细]
  • 本文详细介绍了在PHP中如何获取和处理HTTP头部信息,包括通过cURL获取请求头信息、使用header函数发送响应头以及获取客户端HTTP头部的方法。同时,还探讨了PHP中$_SERVER变量的使用,以获取客户端和服务器的相关信息。 ... [详细]
  • 本文详细介绍了Socket在Linux内核中的实现机制,包括基本的Socket结构、协议操作集以及不同协议下的具体实现。通过这些内容,读者可以更好地理解Socket的工作原理。 ... [详细]
  • 本文介绍了一种在 Android 开发中动态修改 strings.xml 文件中字符串值的有效方法。通过使用占位符,开发者可以在运行时根据需要填充具体的值,从而提高应用的灵活性和可维护性。 ... [详细]
  • Java高级工程师学习路径及面试准备指南
    本文基于一位朋友的PDF面试经验整理,涵盖了Java高级工程师所需掌握的核心知识点,包括数据结构与算法、计算机网络、数据库、操作系统等多个方面,并提供了详细的参考资料和学习建议。 ... [详细]
  • 分布式计算助力链力实现毫秒级安全响应,确保100%数据准确性
    随着分布式计算技术的发展,其在数据存储、文件传输、在线视频、社交平台及去中心化金融等多个领域的应用日益广泛。国际知名企业如Firefox、Google、Opera、Netflix、OpenBazaar等均已采用该技术,推动了技术创新和服务升级。 ... [详细]
  • 本文详细介绍了PHP中的几种超全局变量,包括$GLOBAL、$_SERVER、$_POST、$_GET等,并探讨了AJAX的工作原理及其优缺点。通过具体示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • This article explores the process of integrating Promises into Ext Ajax calls for a more functional programming approach, along with detailed steps on testing these asynchronous operations. ... [详细]
  • 题面:P3178[HAOI2015]树上操作好像其他人都嫌这道题太容易了懒得讲,好吧那我讲。题解:第一个操作和第二个操作本质上是一样的&# ... [详细]
  • 使用jQuery与百度地图API实现地址转经纬度功能
    本文详细介绍了如何利用jQuery和百度地图API将地址转换为经纬度,包括申请API密钥、页面构建及核心代码实现。 ... [详细]
  • 使用 ModelAttribute 实现页面数据自动填充
    本文介绍了如何利用 Spring MVC 中的 ModelAttribute 注解,在页面跳转后自动填充表单数据。主要探讨了两种实现方法及其背后的原理。 ... [详细]
  • 我在尝试将组合框转换为具有自动完成功能时遇到了一个问题,即页面上的列表框也被转换成了自动完成下拉框,而不是保持原有的多选列表框形式。 ... [详细]
  • SPFA算法详解与应用
    当图中包含负权边时,传统的最短路径算法如Dijkstra不再适用,而Bellman-Ford算法虽然能解决问题,但其时间复杂度过高。SPFA算法作为一种改进的Bellman-Ford算法,能够在多数情况下提供更高效的解决方案。本文将详细介绍SPFA算法的原理、实现步骤及其应用场景。 ... [详细]
  • HDU 2537 键盘输入处理
    题目描述了一个名叫Pirates的男孩想要开发一款键盘输入软件,遇到了大小写字母判断的问题。本文提供了该问题的解决方案及实现方法。 ... [详细]
  • 本文详细探讨了select和epoll两种I/O多路复用技术的内部实现原理,分析了它们在处理大量文件描述符时的性能差异,并通过具体示例代码展示了select的工作流程。 ... [详细]
author-avatar
晨风流云
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有