边缘检索与区域提取是我们的课程设计的一个课题。看到这个课题感到十分新颖,因为以前从未接触过这方面的知识。而且由于课程作业要求的语言是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
分享到:
相关推荐
在图像处理领域,图形边缘检测是一项至关重要的技术。它主要用于识别和定位图像中的边界,这些边界通常是不同物体或图像区域之间的分界线。边缘检测在许多应用中都扮演着核心角色,比如计算机视觉、机器学习、自动...
边缘检测和图形面积计算是计算机视觉领域中的基础技术,广泛应用于图像分析、图像识别和机器学习等场景。在本项目中,我们结合了Qt和OpenCV这两个强大的工具,实现了图像的预处理、边缘检测以及图形面积的计算。 Qt...
在本项目中,我们主要探讨的是使用OpenCV库结合C++编程语言,通过Qt界面进行水果识别、颜色识别以及图像处理技术,包括边缘检测。OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,提供了...
在《Visual C++ 图形图像与游戏编程典型》这一主题中,我们主要探讨的是使用Microsoft的Visual C++作为开发工具,进行图形图像处理和游戏编程的相关技术。这涵盖了多个方面,包括图像的读写操作、实时三维地形显示、...
在C++ Builder 6中进行图像处理,开发者可以利用其提供的图形库和编程工具来实现图像的读取、处理和显示,包括边缘检测。 **1. 边缘检测的基本步骤** - **滤波**:消除图像中的噪声,通常使用平滑滤波器如高斯...
本项目"文字兴趣区域提取源码"正是一个基于OCR技术的示例,它利用了VS2013作为开发环境,以及OpenCV 3.*这个强大的计算机视觉库,旨在帮助初学者理解如何检测和提取图像中的文字区域。 OpenCV是一个开源的计算机...
通过边缘检测,可以有效地进行图像分割、目标区域识别以及区域形状提取等操作。边缘跟踪法不仅适用于闭合轮廓,也适用于非闭合轮廓的跟踪,这对于进一步的图像处理工作非常重要。 #### 边缘检测的重要性 边缘检测...
"chap1_2"和"chap1_4"可能是关于更高级的图像处理技术,如边缘检测和特征提取。边缘检测是找出图像中边界的重要步骤,常用算法有Sobel、Prewitt和Canny等。特征提取则是寻找图像中的关键信息,如角点、斑点或纹理,...
接着,使用特征提取技术,如边缘检测、模板匹配或者更高级的深度学习方法,如卷积神经网络(CNN),来提取图像的关键信息。对于文字识别,可能还需要进行文字定位(OCR,Optical Character Recognition)。 【标签...
压缩包中的"第12章 图像边缘检测器的设计与.ppt"很可能是一个详细的讲座或教程,涵盖了边缘检测的基本原理、常见算法的介绍、以及如何在Visual C++环境中实现这些算法的步骤。这样的资料对于学习者来说极其宝贵,...
在C++编程环境中,数据特征提取是一个重要的环节,特别是在计算机视觉、机器人导航和传感器数据分析等领域。标题中的“C++数据特征提取,直线”指的是利用C++编写程序来处理数据,从中识别并提取出直线特征。这通常...
在“tuxiangfenge.rar”压缩包内的“图像分割”文件可能包含相关的源代码、数据集、结果图片或其他资源,这些可以帮助我们深入理解和实践图像分割与区域提取的过程。通过阅读和分析这些代码,我们可以学习到如何在...
其图形用户界面组件和信号与槽机制使得开发者能方便地构建交互式应用。在本项目中,Qt被用来创建一个界面,用户可以通过这个界面加载图片,然后调用OpenCV的边缘检测功能,最后展示处理后的结果。 为了在Qt应用中...
此外,颜色空间转换(例如RGB到HSV)、图像滤波(如高斯滤波、中值滤波)和边缘检测(如Canny算法)等图像处理技术也可能是讨论的重点。 高级部分可能涉及更复杂的图像处理任务,如图像分割、特征提取、模板匹配,...
边缘检测是图像处理中的关键技术,它用于识别图像中物体的边界,从而提取出图像的重要特征。常见的边缘检测算法有Canny算子、Sobel算子、Prewitt算子等。Canny算子是一种多级边缘检测算法,通过高斯滤波器去除噪声,...
4. **LoG(Laplacian of Gaussian)边缘检测算法**:结合高斯平滑滤波器与拉普拉斯算子,用于提取清晰的边缘。 5. **Canny边缘检测算法**:这是一种经典的边缘检测算法,通过多阶段处理来达到精确的边缘定位,同时...
OpenCV是一个广泛使用的计算机视觉库,它包含了大量的图像处理和计算机视觉算法,如图像读取、显示、颜色空间转换、滤波、边缘检测、特征提取等。在Visual C++中,可以创建OpenCV的头文件和库链接,然后编写代码来...
6. **胶囊检测算法**:胶囊检测的具体实现可能会涉及到各种算法,如边缘检测(如Canny或Hough变换)、形状匹配、颜色分割、机器学习模型(如SVM或深度学习网络)等。这些算法用于识别和定位图像中的胶囊。 7. **...
QT是一个跨平台的C++图形用户界面应用程序开发框架,它使得开发带界面的软件更为便捷高效。本文作者赵之源探讨了如何利用QT进行BMP格式图像的边缘检测,这是图像处理中的重要步骤,对于特征提取和模式识别等图像...
7. **图像算法**:源码可能涉及各种图像处理算法,如边缘检测(Canny、Sobel)、图像增强(直方图均衡化)、特征提取(SIFT、SURF)、图像配准等。 8. **DirectX与OpenGL**:这两个是强大的图形库,用于实现高级的...