边缘检索与区域提取是我们的课程设计的一个课题。看到这个课题感到十分新颖,因为以前从未接触过这方面的知识。而且由于课程作业要求的语言是c++,所以选择了 c++ 的一个界面类函数库easyX 下载可见官网 http://www.easyx.cn/
我们将这个课题分为两部分,一是边缘检测,一是区域提取。
关于边缘检测:图像的边缘形成的原因是图像的灰度在某一区域的突然变化使得人眼才有了识别轮廓的功能。所以对于计算机识别边缘我们也可以用数学的方法定量的找出图像中灰度阶跃不连续或是线条不连续的地方,比如说一阶导数的极值点或二阶导数的零点的方法找到边缘。(图片摘自百度)。
当我们继续往下学时,越来越多的概念涌了出来,各种算子、幅度、差分、阈值、卷积运算。这对我这种数学渣渣的确是一种考验。其实我们没必要将边缘检索的数学推导都看懂。我们只要了解它的基本原理后,在运用它的结论就足以达到我们的目的。
我们总结了一下:什么Prewitt算子、Sobel算子,都是对灰度图片的一个变换,我们称这个变换为卷积模板变换,模板变换后,边缘就会被检索出来。首先让我们必须了解什么叫做卷积模板变换。这个博客说的很清楚,大家可以看看。
http://www.cnblogs.com/a-toad/archive/2008/10/24/1318921.html
所以我们根据这个运算规则,将它封装成一个方法,代码及注释如下
//模板操作,包括图像边缘的检测,图像的平滑都会用到这个函数
/*参数的意义
* img 指向图像的指针
* tempWidth tempHeight 模板的宽高
* tempX tempY 模板的中心的x y 坐标
* temp 指向模板数组的指针 tempCoef 模板的系数
* img2 为转化后的照片
*/
bool templateChange(IMAGE *img,int tempWidth,int tempHeight,int tempX,int tempY,float *temp,float tempCoef,IMAGE *img2){
long imgWidth = img->getwidth();
long imgHeight = img->getheight();
//得到原图的内容
DWORD *p = GetImageBuffer(img);
(*img2).Resize(imgWidth,imgHeight);
DWORD *p2 = GetImageBuffer(img2);
//用于暂存模板值
float result;
int endResult;
for (long i=tempY;i<imgHeight-tempHeight+tempY;i++){
for (long j=tempX;j<imgWidth-tempWidth+tempX;j++){
result=0;
//计算模板
for (int k=0;k<tempHeight;k++){
for (int l=0;l<tempWidth;l++){
//逻辑表达式较复杂(横坐标 i-tempy+k 纵坐标 j-tempx+1)
//得到灰度(RGB相同)
int z=GetRValue(p[imgWidth*(i+tempY-k)+j-tempX+l]);
result +=z*temp[k*tempWidth+l];
}
}
result *=tempCoef;
endResult =abs((int)result);
if (endResult>255){
endResult=255;
}
p2[i*imgWidth+j]=RGB(endResult,endResult,endResult);
}
}
return true;
}
了解了这个模板运算,我们反过头来再看各种算子
Sobel算子:
进行的横竖两个方向的模板运算后,遍历整个图片取相同像素点模板运算的最大值。
Prewitt算子:
同Sobel算子,进行的横竖两个方向的模板运算后,遍历整个图片取相同像素点模板运算的最大值。
给出了算法,写程序就很容易了。这里只展示prewitt算子的代码:
void GraphicCut(IMAGE *img){
IMAGE img1,img2;
float temp1[9]={1,0,-1,1,0,-1,1,0,-1};
float tempCoef1=1;
templateChange(img,3,3,1,1,temp1,tempCoef1,&img1);
float temp2[9]={-1,-1,-1,0,0,0,1,1,1};
float tempCoef2=1;
templateChange(img,3,3,1,1,temp2,tempCoef2,&img2);
DWORD *p = GetImageBuffer(img);
DWORD *p1 = GetImageBuffer(&img1);
DWORD *p2 = GetImageBuffer(&img2);
for (long i=0;i<img->getheight();i++)
for (long j=0;j<img->getwidth();j++)
if (p1[i*img->getwidth()+j]<p2[i*img->getwidth()+j]){
p[i*img->getwidth()+j]=p2[i*img->getwidth()+j];
}else{
p[i*img->getwidth()+j]=p1[i*img->getwidth()+j];
}
}
效果图如下:
啃完了边缘检索这块硬骨头后,我们又开始考虑区域要怎么提取。我们最初的想法是做一个类似于搜索的算法,遍历某个区域中的所有点,将这个区域中的像素点提取出来保存到另一幅图片中,就完成了区域提取。
我们最开始想到的是深度搜索,但对于一张500*500的图片来说,这种搜索对时间和空间的消耗都是特别大的,搞不好还会栈溢出。所以我们马上丢弃了这个想法。另一种搜索方法就是广度搜索了,理论上是可行的,所以我们决定试试这种算法。(其实网上有一些经过优化过的搜索算法,如扫描线算法)。
代码如下:
void graphicsFill(IMAGE *img1,IMAGE *img2,IMAGE *img3,int mouseX,int mouseY){
long imgWidth = img1->getwidth();
long imgHeight = img1->getheight();
DWORD *p1 = GetImageBuffer(img1);
DWORD *p2 = GetImageBuffer(img2);
DWORD *p3 = GetImageBuffer(img3);
list<Point> stk;
Point point;
point.x = mouseX;
point.y = mouseY;
stk.push_back(point);
int a[]={0,1,1,1,0,-1,-1,-1};
int b[]={1,1,0,-1,-1,-1,0,1};
while (!stk.empty()){
Point pt;
//获取链表头元素 ,并将其弹出
pt=stk.front(); stk.pop_front();
long y=pt.y;
long x=pt.x;
long z;
int x1,y1;
for (int i=0;i<8;i++){
x1=x+a[i]; y1=y+b[i];
z=abs(long(GetRValue(p1[y*imgWidth+x])-GetRValue(p1[y1*imgWidth+x1])));
if (p2[y1*imgWidth+x1]!=p3[y1*imgWidth+x1]&&z<4){
p3[y1*imgWidth+x1]=p2[y1*imgWidth+x1];
Point pt;
pt.x=x1; pt.y=y1;
stk.push_back(pt);
}
}
}
}
提取效果图片如下:
整的来说,算法的效率还算高。但的确有更好的算法可以去解决这个问题,更好的算法就等读者自己去研究发现了。
- 大小: 94.2 KB
- 大小: 2.8 KB
- 大小: 2.8 KB
- 大小: 11.6 KB
- 大小: 48.2 KB
- 大小: 6 KB
- 大小: 3.4 KB
- 大小: 3.4 KB
分享到:
相关推荐
一个自己写的MFC程序,能够实现一些简单几何图片的检测,比如正方形等规则图形。
很多高级一点的图形图像处理程序,对图像进行去除彩色处理,加入椒盐噪声,利用Prewitte边缘算子法对图像进行边缘提取,医学伪彩色处理,遥感伪彩色处理,利用Roberts边缘算子法对图像进行边缘提取,利用Sobel边缘算子法对...
提取图片轮廓是一款C++实现的图像识别算法,可以清晰的提取图形的边缘轮廓,可参考实现自己的图像识别算法
基于C++的简单图片编辑软件,包含放大,缩小,旋转,噪声,拉普拉斯变换,边缘提取等等功能。
内容索引:VC/C++源码,图形处理,边缘检测,轮廓跟踪,算法 C 图像轮廓跟踪,边沿检测与提取算法源代码,效果不是太好,不过可帮助不懂的朋友了解一些知识。命令行编译过程如下: vcvars32 rc bmp.rc cl edge.c ...
包含边缘提取、分割、傅里叶变换、增强、伪彩色等多种功能
数字图像的边缘检测是图像分割、目标区域的识别、区域形状提取等图像分析领域十分重要的基础,图像理解和分析的第一步往往就是边缘检测,目前它以成为机器视觉研究领域最活跃的课题之一,在工程应用中占有十分重要的...
这是一个在MFC框架中编写的数字图像处理程序,可以实现图像的边缘检测、Hough变换,轮廓提取,轮廓跟踪。
一种快速结构光条纹中心亚像素精度提取方法.caj一种亚像素精度的边缘检测方法.caj
模板匹配人员必看!!!!基于边缘的模板匹配算法,先进行Canny边缘提取,得到边缘的梯度,之后通过金字塔算法和旋转投影变换算法进行匹配!!
图像配准是多传感器图像融合研究中的一项关键技术。...该文研究利用小波变换的方法提取图像的边缘,并对边缘图像作交互方差分析,搜索出最佳交互方差的配准参数。通过对SPOT和TM图像的处理,达到了精度较高的配准效果.
本代码实现了用Canny算子提取图像边缘特征的功能。
一个关于图像边缘轮廓提取的源代码,供大家学习,特别是初学者非常实用
将彩色图像进行灰度变换以后,利用candy算子提取图像边缘。创建一个MFC工程框架,然后通过点击菜单功能实现边缘化提取。
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...
3.掌握数字图像处理的常规算法,尤其对图像的几何校正,边缘检测、区域定位和图像分割原理和算法要有深入的了解。 4. 完成车牌区域的准确定位和分割的设计方案,给出相应的算法,并通过编程实现。 本课题研究的...
通过差异中的“块”进行边缘检测 通用功能待办事项列表: 锐化 撤消/重做堆栈 减少噪音 边缘增强 能够“标记”位置,例如“这个地方是您携带物品的地方” 有一个“参考”图片让患者确切地看到出了什么问题 寻找一...
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...
可视化和计算机图形库(简称 VCGlib)是一个开源、可移植、C++、模板化、无依赖性、用于操作、处理、清理、简化三角形网格的库。 该库由超过 10 万行代码组成,在 GPL 许可下发布,是意大利国家研究委员会研究所 ...
2012-06-12 12:49 8,323,796 Visual C++实现图像获取、处理与分析.rar 2012-06-12 12:49 6,275,839 Visual C++实现数字图像处理源代码.rar 2012-06-12 11:57 182 Visual C++技术内幕摘要笔记.rar 2012-06-12 11:50 3...