VC++与MATLAB混合编程 关于CANNY算子
Matlab引擎实现VC和Matlab混合编程
Matlab引擎实现VC和Matlab混合编程
要想在VC集成环境下利用Matlab引擎实现VC和Matlab的混合编程,一般需要经过以下几个必要的步骤:
(1)Visual C++6.0 编译环境的设置:通过菜单Tools/ Options,打开Visual C++6.0设置属性页,进入Directorie页面,在Show Directories for下拉列表中选择Include Files,添加路径:D:\Matlab6p5\extern\include(在Matlab的安装路径下);再选择下拉列表中的Library Files,添加路径:D:\Matlab6p5\extern\ lib\win32\Microsoft\msvc60(在Matlab的安装路径下)。
编译环境只需设置一次。
(2)添加库文件: 通过菜单Projects|settings,进入Link 页面,在Object/Library Modules 框中,添加库文件名:libmx.lib 、libmat.lib 、libeng.lib。
每个新的工程文件都要单独添加库文件。
(3)在使用engine 函数的程序头文件中包含如下两个头文件:#include "engine.h";#include 。
(4)在应用程序中添加调用Matlab引擎的程序代码:
以上步骤是对VC与Matlab混合编程的编译环境进行设置,在完成了以上基本步骤后就可以利用Matlab引擎库函数engEvalString来调用Matlab的内建函数了。
VC与Matlab混合编程
VC与Matlab混合编程本⽂主要介绍VC与Matlab混合编程的两种⽅法,并详细介绍了VC向Matlab传递复杂数据:结构体的⽅法,有详细代码说明。
Matlab 主要⾯对科学计算、可视化以及交互式程序设计的⾼科技计算环境,但由于Matlab开发平台上开发的程序不能脱离Matlab运⾏环境,因⽽在处理⼀些实际应⽤问题时显得灵活性不⾜,⽽VC++则在⼀定程度上能够弥补这⼀漏洞,因此,将⼆者结合共⽤,各献其长,可以为科研⼯作和⼯程开发提供更为强⼤的技术⽀持。
Matlab作为控制系统设计的⼀种通⽤⼯具,它可以很⽅便的和VC进⾏连接。
⼀般⽽⾔,Matlab与VC混合编程的实现⽅法有很多种,这⾥主要介绍以下两种:1. VC调⽤Matlab Engine的⽅式:Matlab Engine是⼀组Matlab提供的接⼝函数,⽀持C/C++语⾔,Matlab Engine采⽤C/S(客户机/服务器)模式,Matlab作为后台服务器,⽽C/C++程序作为前台客户机,向Matlab Engine传递执⾏命令和数据信息,从Matlab Engine接收执⾏结果。
⽤户可以在前台应⽤程序中调⽤这些接⼝函数,实现对Matlab Engine的控制。
采⽤这种⽅法⼏乎能利⽤Matlab全部功能,但是需要在机器上安装Matlab软件,缺点是执⾏效率较低。
下⾯简单介绍下这种⽅式的实现步骤:1.1 API接⼝介绍先来介绍⼀组Matlab提供的引擎API接⼝:(仅作简单功能介绍,详细参数说明请参考Matlab帮助)Engine* engOpen(const char* startcmd)启动Matlab引擎int engClose(Engine* ep) 关闭Matlab引擎int engEvalString(Engine* ep, const char* string)执⾏Matlab表达式mxArray* engGetArray(Engine* ep, const char* name)获取⼀个变量数组的值int engPutArray(engine* ep, const mxArray* mp)设置⼀个变量数组的值int engPutVariable(Engine *ep, const char *name, const mxArray *pm)同上mxArray *engGetVariable(Engine *ep, const char *name)获取⼀个变量int engOutputBuffer(Engine* eP,char* p,int n)获取输出字符串1.2 VC环境配置要想在VC集成环境下调⽤Matlab引擎实现VC和Matlab的混合编程,⼀般需要经过以下⼏个必要的步骤:(以下以Matlab2008a和VS2005版本为例)(1)添加include路径:将“\extern\include”(在Matlab的安装路径下)路劲添加到VC编译器的include下(2)添加lib路径:将“\extern \lib\win32\microsoft” (在Matlab的安装路径下) 路径添加到VC编译器的lib下(3)加载lib:需要加载⾄少libmx.lib、libmat.lib、libeng.lib三个库(4)include头⽂件:在要使⽤ engine 函数的地⽅包含engine.h头⽂件1.3 引擎调⽤接下来就可以在VC中调⽤Matlab引擎了,简单的⽰例代码如下:#include "engine.h"#pragma comment(lib, "libeng.lib")#pragma comment(lib, "libmx.lib")#pragma comment(lib, "libmat.lib")void TestDeno(){Engine* pEng = NULL;if (!(pEng = engOpen(NULL))){printf("Open matlab enging fail!");return;}//call Engine plot A*sin(t)+B A=2 B=1mxArray *A = NULL;double init = 2;A = mxCreateDoubleMatrix(1, 1, mxREAL);memcpy((void*) mxGetPr(A), (void*)&init, sizeof (double));engPutVariable(pEng, "A", A);init = 1;memcpy((void*) mxGetPr(A), (void*)&init, sizeof (double));engPutVariable(pEng, "B", A);mxDestroyArray(A);Sleep(3*60*1000);engEvalString(pEng, "t=0:0.2:7;plot(t,A*sin(t)+B);");if(NULL != pEng){engClose(pEng);}}⽰例代码通过VC调⽤Matlab引擎,绘制正弦曲线,相对简单,就不再详细解释,效图如下:2. VC调⽤Matlab DLL的⽅式DLL是⼀个可执⾏的⼆进制⽂件。
matlab 中canny算法
matlab 中canny算法什么是Canny算法?Canny算法是一种常用于图像边缘检测的计算机视觉算法。
它由约翰·Canny在1986年提出,目的是在保持最佳信噪比的同时准确地检测出图像中的边缘。
Canny算法的步骤是什么?Canny算法包括以下几个步骤:1. 噪声抑制:由于图像中常常存在噪声,因此第一步是对图像进行平滑处理以抑制噪声。
常用的方法是应用高斯滤波器。
2. 计算梯度:通过计算图像的梯度来确定边缘的强度和方向。
梯度计算通常使用Sobel算子,它可以有效地检测图像中的边缘。
3. 非极大值抑制:在计算梯度之后,需要对梯度幅度图像进行非极大值抑制。
这一步的目的是去除那些不是真正边缘的像素。
4. 双阈值检测:在经过非极大值抑制之后,需要对幅度图像进行阈值处理。
Canny算法使用双阈值检测来确定强边缘和弱边缘。
任何高于高阈值的像素被认为是强边缘,低于低阈值的像素被认为是弱边缘。
5. 边缘跟踪:最后一步是利用边缘跟踪算法来连接强边缘。
边缘跟踪算法基于弱边缘像素与强边缘像素的连接关系,通过追踪弱边缘像素与强边缘像素的路径来确定最终的边缘。
Canny算法的优缺点是什么?Canny算法有以下几个优点:1. 准确性:Canny算法能够准确地检测图像中的边缘,尤其在边缘区域有噪声的情况下。
2. 低错误率:相比于其他边缘检测算法,Canny算法的错误率较低,能够有效地排除非边缘像素。
3. 单一边缘:Canny算法仅提取单一像素的边缘,不会将边缘模糊化。
虽然Canny算法有许多优点,但也存在一些缺点:1. 计算量大:Canny算法需要进行多次计算,包括高斯滤波、梯度计算和非极大值抑制等,因此计算量较大。
2. 参数选择:Canny算法涉及到多个参数的选择,如高斯滤波器的大小和标准差、双阈值检测的高低阈值等。
不同的参数选择可能导致不同的结果。
3. 边缘连接:Canny算法在边缘连接过程中可能会产生断裂的边缘。
matlabcanny算子边缘检测函数代码
分享到:2012-04-24 20:42网友采纳clcclear allclose allI = imread('cameraman.tif'); % 读入图像imshow(I);title('原图')BW1 = edge(I,'canny'); % 调用canny函数figure,imshow(BW1); % 显示分割后的图像,即梯度图像title('Canny')用Lena标准检测图像,图像与代码下面注明了是哪张图像。
一、没有噪声时的检测结果 1 原始图像2 Sobel算子边缘检测3 Prewitt算子边缘检测4 Roberts算子边缘检测5 Laplace算子边缘检测6 Canny算子边缘检测二、加入高斯噪声(μ=0,σ^2=0.01)检测结果 1 原始图像2 Sobel算子边缘检测3 Prewitt算子边缘检测4 Roberts算子边缘检测5 Laplace算子边缘检测6 Canny算子边缘检测三、加入高斯噪声(μ=0,σ^2=0.02)检测结果 1 原始图像2 Sobel算子边缘检测3 Prewitt算子边缘检测4 Roberts算子边缘检测5 Laplace算子边缘检测6 Canny算子边缘检测clear all; close all;warning off all;I = imread('lena.bmp'); %%如果是其他类型图像,请先转换为灰度图%%没有噪声时的检测结果BW_sobel = edge(I,'sobel');BW_prewitt = edge(I,'prewitt');BW_roberts = edge(I,'roberts');BW_laplace = edge(I,'log');BW_canny = edge(I,'canny'); figure(1);subplot(2,3,1),imshow(I),xlabel('原始图像');subplot(2,3,2),imshow(BW_sobel),xlabel('sobel检测');subplot(2,3,3),imshow(BW_prewitt),xlabel('prewitt检测');subplot(2,3,4),imshow(BW_roberts),xlabel('roberts检测');subplot(2,3,5),imshow(BW_laplace),xlabel('laplace检测');subplot(2,3,6),imshow(BW_canny),xlabel('canny检测');%%加入高斯噪声(μ=0,σ^2=0.01)检测结果I_g1 = imnoise(I,'gaussian',0,0.01);BW_sobel = edge(I_g1,'sobel');BW_prewitt = edge(I_g1,'prewitt');BW_roberts = edge(I_g1,'roberts');BW_laplace = edge(I_g1,'log');BW_canny = edge(I_g1,'canny'); figure(2);subplot(2,3,1),imshow(I_g1),xlabel('加入高斯噪声(μ=0,σ^2=0.01)图像'); subplot(2,3,2),imshow(BW_sobel),xlabel('sobel检测');subplot(2,3,3),imshow(BW_prewitt),xlabel('prewitt检测');subplot(2,3,4),imshow(BW_roberts),xlabel('roberts检测');subplot(2,3,5),imshow(BW_laplace),xlabel('laplace检测');subplot(2,3,6),imshow(BW_canny),xlabel('canny检测');%%加入高斯噪声(μ=0,σ^2=0.02)检测结果I_g2 = imnoise(I,'gaussian',0,0.02);BW_sobel = edge(I_g2,'sobel');BW_prewitt = edge(I_g2,'prewitt');BW_roberts = edge(I_g2,'roberts');BW_laplace = edge(I_g2,'log');BW_canny = edge(I_g2,'canny'); figure(3);subplot(2,3,1),imshow(I_g2),xlabel('加入高斯噪声(μ=0,σ^2=0.02)图像'); subplot(2,3,2),imshow(BW_sobel),xlabel('sobel检测');subplot(2,3,3),imshow(BW_prewitt),xlabel('prewitt检测');subplot(2,3,4),imshow(BW_roberts),xlabel('roberts检测');subplot(2,3,5),imshow(BW_laplace),xlabel('laplace检测');subplot(2,3,6),imshow(BW_canny),xlabel('canny检测');199条建筑设计知识1. 公共建筑通常以交通、使用、辅助三种空间组成2. 美国著名建筑师沙利文提出的名言‘形式由功能而来’3. 密斯.凡.德.罗设计的巴塞罗那博览会德国馆采用的是‘自由灵活的空间组合’开创了流动空间的新概念4. 美国纽约赖特设计的古根海姆美术馆的展厅空间布置采用形式是串联式5. 电影放映院不需采光6. 点式住宅可设天井或平面凹凸布置可增加外墙面,有利于每层户数较多时的采光和通风7. 对结构形式有规定性的有大小和容量、物理环境、形状的规定性8. 功能与流线分析是现代建筑设计最常用的手段9. 垂直方向高的建筑需要考虑透视变形的矫正10. 橙色是暖色,而紫色含有蓝色的成分,所以偏冷;青色比黄色冷、红色比黄色暖、蓝色比绿色冷11. 同样大小冷色调较暖色调给人的感觉要大12. 同样距离,暖色较冷色给人以靠近感13. 为保持室内空间稳定感,房间的低处宜采用低明度色彩14. 冷色调给人以幽雅宁静的气氛15. 色相、明度、彩度是色彩的三要素;三元色为红、黄、蓝16. 尺度的概念是建筑物整体或局部给人的视角印象大小和其实际大小的关系17. 美的比例,必然正确的体现材料的力学特征18. 不同文化形成独特的比例形式19. 西方古典建筑高度与开间的比例,愈高大愈狭长,愈低矮愈宽阔20. ‘稳定’所涉及的要素是上与下之间的相对轻重关系的处理21. 人眼观赏规律H 18°~45°局部、细部2H 18°~27°整体3H <18°整体及环境22. 黄金分隔比例为1:1.61823. 通风屋面只能隔离太阳辐射不能保温,适宜于南方24. 总图布置要因地制宜,建筑物与周围环境之间关系紧凑,节约因地;适当处理个体与群体,空间与体形,绿化和小品的关系;合理解决采光、通风、朝向、交通与人流的组织25. 热水系统舒适稳定适用于居住建筑和托幼蒸汽系统加热快,适用于间歇采暖建筑如会堂、剧场26. 渐变具有韵律感27. 要使一座建筑显得富有活力,形式生动,在构图中应采用对比的手法对比的手法有轴线对比、体量对比、方向对比、虚实对比、色彩对比28. 要使柱子看起来显得细一些,可以采用暗色和冷色29. 巴西国会大厅在体型组合中采用了对比与协调的手法30. 展览建筑应使用穿套式的空间组合形式31. 室外空间的构成,主要依赖于建筑和建筑群体组合32. 在意大利威尼斯的圣马可广场的布局中,采用了强调了各种空间之间的对比33. 当坡地坡度较缓时,应采用平行等高线布置34. 建筑的有效面积=建筑面积-结构面积35. 加大开窗面积的方法来解决采光和通风问题较易办到36. 中国古代木结构大致可分为抬梁式、穿斗式和井干式三种37. 建筑构图原理的基本范畴有主从与重点、对比与呼应、均衡与稳定、节奏与韵律和比例与尺度38. 建筑构图的基本规律是多样统一39. 超过8层的建筑中,电梯就成为主要的交通工具了40. 建筑的模数分为基本模数、扩大模数和分模数41. 建筑楼梯梯段的最大坡度不宜超过38°42. 住宅起居室、卧室、厨房应直接采光,窗地比为1/7,其他为1/1243. 住宅套内楼梯梯段的最小净宽两边墙的0.9M,一边临空的0.75M住宅室内楼梯踏步宽不应小于0.22M,踏步高度不应小大0.20M44. 住宅底层严禁布置火灾危险性甲乙类物质的商店,不应布置产生噪声的娱乐场所45. 地下室、贮藏室等房间的最低净高不应低于2.0米46. 室内坡道水平投影长度超过15米时,宜设休息平台47. 外墙内保温所占面积不计入使用面积烟道、风道、管道井不计入使用面积阳台面积不计入使用面积壁柜应计入使用面积48. 旋转楼梯两级的平面角度不大于10度,且每级离内侧扶手中心0.25处的踏步宽度要大于0.22米49. 两个安全出口之间的净距不应小于5米50. 楼梯正面门扇开足时宜保持0.6米平台净宽,侧墙门口距踏步不宜小于0.4米,其门扇开足时不应减少梯段的净宽35. 加大开窗面积的方法来解决采光和通风问题较易办到36. 中国古代木结构大致可分为抬梁式、穿斗式和井干式三种37. 建筑构图原理的基本范畴有主从与重点、对比与呼应、均衡与稳定、节奏与韵律和比例与尺度38. 建筑构图的基本规律是多样统一39. 超过8层的建筑中,电梯就成为主要的交通工具了40. 建筑的模数分为基本模数、扩大模数和分模数41. 建筑楼梯梯段的最大坡度不宜超过38°42. 住宅起居室、卧室、厨房应直接采光,窗地比为1/7,其他为1/1243. 住宅套内楼梯梯段的最小净宽两边墙的0.9M,一边临空的0.75M住宅室内楼梯踏步宽不应小于0.22M,踏步高度不应小大0.20M44. 住宅底层严禁布置火灾危险性甲乙类物质的商店,不应布置产生噪声的娱乐场所45. 地下室、贮藏室等房间的最低净高不应低于2.0米46. 室内坡道水平投影长度超过15米时,宜设休息平台47. 外墙内保温所占面积不计入使用面积烟道、风道、管道井不计入使用面积阳台面积不计入使用面积壁柜应计入使用面积48. 旋转楼梯两级的平面角度不大于10度,且每级离内侧扶手中心0.25处的踏步宽度要大于0.22米49. 两个安全出口之间的净距不应小于5米50. 楼梯正面门扇开足时宜保持0.6米平台净宽,侧墙门口距踏步不宜小于0.4米,其门扇开足时不应减少梯段的净宽35. 加大开窗面积的方法来解决采光和通风问题较易办到36. 中国古代木结构大致可分为抬梁式、穿斗式和井干式三种37. 建筑构图原理的基本范畴有主从与重点、对比与呼应、均衡与稳定、节奏与韵律和比例与尺度38. 建筑构图的基本规律是多样统一39. 超过8层的建筑中,电梯就成为主要的交通工具了40. 建筑的模数分为基本模数、扩大模数和分模数41. 建筑楼梯梯段的最大坡度不宜超过38°42. 住宅起居室、卧室、厨房应直接采光,窗地比为1/7,其他为1/1243. 住宅套内楼梯梯段的最小净宽两边墙的0.9M,一边临空的0.75M住宅室内楼梯踏步宽不应小于0.22M,踏步高度不应小大0.20M44. 住宅底层严禁布置火灾危险性甲乙类物质的商店,不应布置产生噪声的娱乐场所45. 地下室、贮藏室等房间的最低净高不应低于2.0米46. 室内坡道水平投影长度超过15米时,宜设休息平台47. 外墙内保温所占面积不计入使用面积烟道、风道、管道井不计入使用面积阳台面积不计入使用面积壁柜应计入使用面积48. 旋转楼梯两级的平面角度不大于10度,且每级离内侧扶手中心0.25处的踏步宽度要大于0.22米49. 两个安全出口之间的净距不应小于5米50. 楼梯正面门扇开足时宜保持0.6米平台净宽,侧墙门口距踏步不宜小于0.4米,其门扇开足时不应减少梯段的净宽51. 入地下车库的坡道端部宜设挡水反坡和横向通长雨水篦子52. 室内台阶宜150*300;室外台阶宽宜350左右,高宽比不宜大于1:2.553. 住宅公用楼梯踏步宽不应小于0.26M,踏步高度不应大于0.175M54. 梯段宽度不应小于1.1M(6层及以下一边设栏杆的可为1.0M),净空高度2.2M55. 休息平台宽度应大于梯段宽度,且不应小于1.2M,净空高度2.0M56. 梯扶手高度0.9M,水平段栏杆长度大于0.5M时应为1.05M57. 楼梯垂直杆件净空不应大于0.11M,梯井净空宽大于0.11M时应采取防护措施58. 门洞共用外门宽1.2M,户门卧室起居室0.9M,厨房0.8M,卫生间及阳台门0.7M,所有门洞高为2.0M59. 住宅层高不宜高于2.8M60. 卧室起居室净高≥2.4M,其局部净高≥2.1M(且其不应大于使用面积的1/3)61. 利用坡顶作起居室卧室的,一半面积净高不应低于2.1M利用坡顶空间时,净高低于1.2M处不计使用面积;1.2--2.1M计一半使用面积;高于2.1M全计使用面积62. 放家具墙面长3M,无直接采光的厅面积不应大于10M263. 厨房面积Ⅰ、Ⅱ≥4M2;Ⅲ、Ⅳ≥5M264. 厨房净宽单面设备不应小于1.5M;双面布置设备间净距不应小于0.9M65. 对于大套住宅,其使用面积必须满足45平方米66. 住宅套型共分四类使用面积分别为34、45、56、68M267. 单人卧室≥6M2;双人卧室≥10M2;兼起居室卧室≥12M2;68. 卫生间面积三件3M2;二件2--2.5M2;一件1.1M269. 厨房、卫生间净高2.2M70. 住宅楼梯窗台距楼地面净高度低于0.9米时,不论窗开启与否,均应有防护措施71. 阳台栏杆净高1.05M;中高层为1.1M(但要<1.2);杆件净距0.1172. 无外窗的卫生间应设置防回流构造的排气通风道、预留排气机械的位置、门下设进风百叶窗或与地面间留出一定缝隙73. 每套应设阳台或平台、应设置晾衣设施、顶层应设雨罩;阳台、雨罩均应作有组织排水;阳台宜做防水;雨罩应做防水74. 寒冷、夏热冬冷和夏热冬暖地区的住宅,西面应采取遮阳措施75. 严寒地区的住宅出入口,各种朝向均应设防寒门斗或保温门76. 住宅建筑中不宜设置的附属公共用房有锅炉房、变压器室、易燃易爆化学物品商店但有厨房的饮食店可设77. 住宅设计应考虑防触电、防盗、防坠落78. 跃层指套内空间跨跃两楼层及以上的住宅79. 在坡地上建住宅,当建筑物与等高线垂直时,采用跌落方式较为经济80. 住宅建筑工程评估指标体系表中有一级和二级指标81. 7层及以上(16米)住宅必须设电梯82. 宿舍最高居住层的楼地面距入口层地面的高度大于20米时,应设电梯83. 医院病房楼,设有空调的多层旅馆,超过5层的公建室内疏散楼梯,均应设置封闭楼梯间(包括首层扩大封闭楼梯间)设歌舞厅放映厅且超过3层的地上建筑,应设封闭楼梯间。
浅析VC与matlab接口编程(一)
浅析VC与matlab接口编程(一)作者:孙科除了使用MATCOM之外,matlab与vc的混合编程还有其他的几种方法:1 通过matlab engine方式。
此种方法需要在机器上安装matlab软件,而且执行效率低,因此在实际应用中不常采用这种方法,在软件开发中也不可行,比较适合个人使用或做演示用。
2 直接调用matlab的c/c++数学函数库。
vc中可以直接使用matlab提供的c/c++数学函数,此方法需要对c/c++语言非常熟悉。
3 用matlab自带的matlab compiler.此种方法有很多限制:(1)不能转换脚本m文件,只能转换m函数;(2)不能使用matlab对象;(3)不能用input或者eval操作matlab空间变量;(4)不能动态的命名变量,然后用load或者save命令来操作,不能对使用load指令装载普通文本文件的m文件操作;(5)不能处理具有嵌套调用其他m文件的m文件;(6)不能使用matlab内联函数(7)不能对使用了java接口的matlab代码文件使用4 使用matlab的combuild工具:该方法简单,通用性强,几乎可以使用matlab的任何函数,因此在程序较大,调用函数较多时使用起来效果很好,此方法也是mathworks公司推荐的使用方法;5 使用matcom工具。
相比其他方法而言,有下列优点:(1)转换过程简单,容易实现;(2)可以方便的生成dll和exe文件;(3)不仅可以转换独立的脚本文件,也可以转换嵌套的脚本文件;(4)设置环境后,可以使用matlab工具箱函数;其缺点是:(1)对struct等类的支持有缺陷;(2)部分绘图语句无法实现或得不到准确的图像,尤其是三维图像。
在不涉及到三维作图以及m文件不大的情况下,使用效果很好。
Matcom是mathTools公司推出的一个能将M文件转化成相同功能C++代码的工具。
相比Matlab自带的编译器Compiler,用Matcom转化代码要简单和方便得多。
matlabcanny边缘检测代码接霍夫变换-概述说明以及解释
matlabcanny边缘检测代码接霍夫变换-概述说明以及解释1.引言1.1 概述边缘检测是图像处理中的一个重要任务,它广泛应用于计算机视觉、图像分析和模式识别等领域。
边缘检测的目标是找到图像中不同区域之间的边界,并将其表示为像素强度的变化。
Canny边缘检测算法是一种经典且常用的边缘检测方法。
它通过一系列的图像处理步骤来提取图像中的边缘信息。
Canny算法的特点是能够检测出细且准确的边缘,并且对于图像中的噪声具有较好的抵抗能力。
Matlab是一种功能强大的数学软件,广泛应用于科学计算、数据可视化和图像处理等领域。
Matlab提供了丰富的图像处理函数和工具箱,其中包括了Canny边缘检测的实现代码。
本文的主要目的是介绍Matlab中Canny边缘检测的代码实现,并结合Hough变换算法进行边缘检测的应用。
通过使用Matlab中的相关函数和工具,我们可以有效地实现Canny边缘检测,并结合Hough变换来进一步处理和分析图像中的边缘特征。
本文将首先回顾Canny边缘检测算法的原理和步骤,然后介绍Matlab中的Canny边缘检测代码的使用方法。
接着,我们将介绍Hough 变换算法的原理和应用,并展示如何将Canny边缘检测与Hough变换相结合来实现更精确的边缘检测。
最后,我们将对Canny边缘检测和Hough变换的优缺点进行讨论,总结这两种方法在边缘检测中的应用。
同时,我们也将展望未来的研究方向,探讨如何进一步改进和优化边缘检测算法,以满足不断发展的图像处理需求。
通过阅读本文,读者将能够理解Canny边缘检测算法和Hough变换算法的原理,掌握Matlab中相关代码的使用方法,并了解边缘检测在实际应用中的优势和局限性。
希望本文能为读者在图像处理领域的学习和研究提供一定的帮助和启示。
文章结构是指文章的整体框架和组织形式。
一个良好的文章结构可以使读者更好地理解和领会文章的内容,同时也有助于文章的逻辑性和条理性。
matlab中canny边缘检测算法的实现
matlab中canny边缘检测算法的实现【Matlab中Canny边缘检测算法的实现】引言:边缘检测是计算机视觉和图像处理领域中的一项重要任务,主要用于提取图像中物体的轮廓或边界。
在边缘检测算法中,Canny算法是一种非常经典和常用的方法,由John F. Canny于1986年提出。
该算法被广泛应用于计算机视觉领域,实现了较好的边缘检测效果和低误报率。
本文将详细介绍在Matlab中实现Canny边缘检测算法的步骤和原理。
1. 算法原理:Canny边缘检测算法主要包含以下几个步骤:(1)使用高斯滤波平滑图像,减少噪声的影响。
(2)计算图像的梯度幅值和方向,确定图像中的强边缘。
(3)应用非极大值抑制算法,细化边缘。
(4)通过双阈值处理,进一步筛选边缘像素。
(5)连接边缘像素,得到最终的边缘结果。
2. 算法实现步骤:在Matlab中,我们可以利用内置函数和库函数来实现Canny边缘检测算法。
下面将一步一步介绍具体的实现过程。
2.1 加载图像:首先,我们需要加载一张待处理的图像。
可以使用imread函数加载图像,例如:img = imread('image.jpg');2.2 灰度化处理:Canny算法通常在灰度图像上进行,因此我们需要将彩色图像转换为灰度图像。
可以使用rgb2gray函数实现:grayImg = rgb2gray(img);2.3 高斯滤波:为了减少噪声的影响,我们需要对图像进行平滑处理。
可以使用fspecial函数创建高斯滤波器,然后使用imfilter函数对灰度图像进行滤波。
示例代码如下:filterSize = 5; % 设置滤波器尺寸sigma = 1; % 设置高斯分布的标准差gaussianFilter = fspecial('gaussian', [filterSize filterSize], sigma); smoothImg = imfilter(grayImg, gaussianFilter, 'symmetric');2.4 计算梯度幅值和方向:接下来,我们需要计算图像中每个像素的梯度幅值和方向。
matlab实现自适应阈值的canny算法
一、背景介绍随着数字图像处理技术的不断发展,图像边缘检测一直是计算机视觉和图像处理领域的关键问题之一。
Canny算法作为一种经典的边缘检测算法,在实际应用中具有较高的准确性和鲁棒性,因此被广泛应用于各种图像处理任务中。
Canny算法的核心思想是利用图像的梯度信息来检测图像中的边缘,同时通过非极大值抑制和双阈值检测来提取最终的边缘信息。
二、Canny算法原理1. 高斯模糊:为了减少图像中的噪声对边缘检测的影响,Canny算法首先对图像进行高斯模糊处理,通过平滑图像来减少噪声的影响。
2. 梯度计算:接下来,Canny算法利用Sobel算子计算图像的梯度幅值和方向,得到图像的梯度信息。
3. 非极大值抑制:Canny算法通过比较图像中每个像素点的梯度方向,来抑制非边缘像素,从而得到更细化的边缘信息。
4. 双阈值检测:Canny算法利用双阈值检测来进一步筛选边缘像素,从而得到最终的边缘信息。
三、Matlab实现Canny算法1. 读取图像:使用Matlab的imread函数读取待处理的图像,并将其转换为灰度图像。
2. 高斯模糊:利用Matlab中的imgaussfilt函数对灰度图像进行高斯模糊处理,减少图像中的噪声。
3. 计算梯度:使用Matlab中的imgradient函数计算图像的梯度幅值和方向。
4. 非极大值抑制:编写代码实现对图像的非极大值抑制处理,保留图像中的边缘像素。
5. 双阈值检测:通过设定合适的高低阈值,使用Matlab中的imbinarize函数对图像进行双阈值检测,得到最终的边缘信息。
6. 显示结果:使用Matlab中的imshow函数将原始图像和处理后的边缘图像进行显示,观察算法的效果。
四、自适应阈值优化1. 传统Canny算法中,阈值的设定是一个固定的数值,对于不同图像可能会产生较大的误差。
2. 为了进一步提高Canny算法的准确性和鲁棒性,在阈值的设定上可以引入自适应阈值技术。
canny边缘检测算子的c源代码
canny边缘检测算子的c源代码canny算子代码void CreatGauss(double sigma, double **pdKernel, int *pnWidowSize);void GaussianSmooth(SIZE sz, LPBYTE pGray, LPBYTE pResult, double sigma);void Grad(SIZE sz, LPBYTE pGray, int *pGradX, int *pGradY, int *pMag);void NonmaxSuppress(int *pMag, int *pGradX, int *pGradY, SIZE sz, LPBYTE pNSRst);void EstimateThreshold(int *pMag, SIZE sz, int *pThrHigh, int *pThrLow, LPBYTE pGray, double dRatHigh, double dRatLow);void Hysteresis(int *pMag, SIZE sz, double dRatLow, double dRatHigh, LPBYTE pResult); void TraceEdge(int y, int x, int nThrLow, LPBYTE pResult, int *pMag, SIZE sz);void Canny(LPBYTE pGray, SIZE sz, double sigma, double dRatLow,double dRatHigh, LPBYTE pResult);#include "afx.h"#include "math.h"#include "canny.h"// 一维高斯分布函数,用于平滑函数中生成的高斯滤波系数void CreatGauss(double sigma, double **pdKernel, int *pnWidowSize){LONG i;//数组中心点int nCenter;//数组中一点到中心点距离double dDis;//中间变量double dValue;double dSum;dSum = 0;// [-3*sigma,3*sigma] 以内数据,会覆盖绝大部分滤波系数*pnWidowSize = 1+ 2*ceil(3*sigma);nCenter = (*pnWidowSize)/2;*pdKernel = new double[*pnWidowSize];//生成高斯数据for(i=0;i<(*pnWidowSize);i++){dDis = double(i - nCenter);dValue = exp(-(1/2)*dDis*dDis/(sigma*sigma))/(sqrt(2*3.1415926)*sigma);(*pdKernel)[i] = dValue;dSum+=dValue;}//归一化for(i=0;i<(*pnWidowSize);i++){(*pdKernel)[i]/=dSum;}}//用高斯滤波器平滑原图像void GaussianSmooth(SIZE sz, LPBYTE pGray, LPBYTE pResult, double sigma) {LONG x, y;LONG i;//高斯滤波器长度int nWindowSize;//窗口长度int nLen;//一维高斯滤波器double *pdKernel;//高斯系数与图像数据的点乘double dDotMul;//滤波系数总和double dWeightSum;double *pdTemp;pdTemp = new double[sz.cx*sz.cy];//产生一维高斯数据CreatGauss(sigma, &pdKernel, &nWindowSize);nLen = nWindowSize/2;//x方向滤波for(y=0;y<sz.cy;y++){for(x=0;x<sz.cx;x++){dDotMul = 0;dWeightSum = 0;for(i=(-nLen);i<=nLen;i++){//判断是否在图像内部if((i+x)>=0 && (i+x)<sz.cx){dDotMul+=(double)pGray[y*sz.cx+(i+x)] * pdKernel[nLen+i]; dWeightSum += pdKernel[nLen+i];}}pdTemp[y*sz.cx+x] = dDotMul/dWeightSum;}}//y方向滤波for(x=0; x<sz.cx;x++){for(y=0; y<sz.cy; y++){dDotMul = 0;dWeightSum = 0;for(i=(-nLen);i<=nLen;i++){if((i+y)>=0 && (i+y)< sz.cy){dDotMul += (double)pdTemp[(y+i)*sz.cx+x]*pdKernel[nLen+i]; dWeightSum += pdKernel[nLen+i];}}pResult[y*sz.cx+x] = (unsigned char)dDotMul/dWeightSum;}}delete []pdKernel;pdKernel = NULL;delete []pdTemp;pdTemp = NULL;}// 方向导数,求梯度void Grad(SIZE sz, LPBYTE pGray,int *pGradX, int *pGradY, int *pMag) {LONG y,x;//x方向的方向导数for(y=1;y<sz.cy-1;y++){for(x=1;x<sz.cx-1;x++){pGradX[y*sz.cx +x] = (int)( pGray[y*sz.cx+x+1]-pGray[y*sz.cx+ x-1] );}}//y方向方向导数for(x=1;x<sz.cx-1;x++){for(y=1;y<sz.cy-1;y++){pGradY[y*sz.cx +x] = (int)(pGray[(y+1)*sz.cx +x] - pGray[(y-1)*sz.cx +x]); }}//求梯度//中间变量double dSqt1;double dSqt2;for(y=0; y<sz.cy; y++){for(x=0; x<sz.cx; x++){//二阶范数求梯度dSqt1 = pGradX[y*sz.cx + x]*pGradX[y*sz.cx + x];dSqt2 = pGradY[y*sz.cx + x]*pGradY[y*sz.cx + x];pMag[y*sz.cx+x] = (int)(sqrt(dSqt1+dSqt2)+0.5);}}}//非最大抑制void NonmaxSuppress(int *pMag, int *pGradX, int *pGradY, SIZE sz, LPBYTE pNSRst) {LONG y,x;int nPos;//梯度分量int gx;int gy;//中间变量int g1,g2,g3,g4;double weight;double dTmp,dTmp1,dTmp2;//设置图像边缘为不可能的分界点for(x=0;x<sz.cx;x++){pNSRst[x] = 0;pNSRst[(sz.cy-1)*sz.cx+x] = 0;}for(y=0;y<sz.cy;y++){pNSRst[y*sz.cx] = 0;pNSRst[y*sz.cx + sz.cx-1] = 0;}for(y=1;y<sz.cy-1;y++){for(x=1;x<sz.cx-1;x++){//当前点nPos = y*sz.cx + x;//如果当前像素梯度幅度为0,则不是边界点if(pMag[nPos] == 0){pNSRst[nPos] = 0;}else{//当前点的梯度幅度dTmp = pMag[nPos];//x,y方向导数gx = pGradX[nPos];gy = pGradY[nPos];//如果方向导数y分量比x分量大,说明导数方向趋向于y分量if(abs(gy) > abs(gx)){//计算插值比例weight = fabs(gx)/fabs(gy);g2 = pMag[nPos-sz.cx];g4 = pMag[nPos+sz.cx];//如果x,y两个方向导数的符号相同//C 为当前像素,与g1-g4 的位置关系为://g1 g2// C// g4 g3if(gx*gy>0){g1 = pMag[nPos-sz.cx-1];g3 = pMag[nPos+sz.cx+1];}//如果x,y两个方向的方向导数方向相反//C是当前像素,与g1-g4的关系为:// g2 g1// C// g3 g4else{g1 = pMag[nPos-sz.cx+1];g3 = pMag[nPos+sz.cx-1];}}//如果方向导数x分量比y分量大,说明导数的方向趋向于x分量else{//插值比例weight = fabs(gy)/fabs(gx);g2 = pMag[nPos+1];g4 = pMag[nPos-1];//如果x,y两个方向的方向导数符号相同//当前像素C与g1-g4的关系为// g3// g4 C g2// g1if(gx * gy > 0){g1 = pMag[nPos+sz.cx+1];g3 = pMag[nPos-sz.cx-1];}//如果x,y两个方向导数的方向相反// C与g1-g4的关系为// g1// g4 C g2// g3else{g1 = pMag[nPos-sz.cx+1];g3 = pMag[nPos+sz.cx-1];}}//利用g1-g4 对梯度进行插值{dTmp1 = weight*g1 + (1-weight)*g2;dTmp2 = weight*g3 + (1-weight)*g4;//当前像素的梯度是局部的最大值//该点可能是边界点if(dTmp>=dTmp1 && dTmp>=dTmp2){pNSRst[nPos] = 128;}{//不可能是边界点pNSRst[nPos] = 0;}}}}}}// 统计pMag的直方图,判定阈值void EstimateThreshold(int *pMag, SIZE sz, int *pThrHigh, int *pThrLow, LPBYTE pGray, double dRatHigh, double dRatLow){LONG y,x,k;//该数组的大小和梯度值的范围有关,如果采用本程序的算法//那么梯度的范围不会超过pow(2,10)int nHist[256];//可能边界数int nEdgeNum;//最大梯度数int nMaxMag;int nHighCount;nMaxMag = 0;//初始化for(k=0;k<256;k++){nHist[k] = 0;}//统计直方图,利用直方图计算阈值for(y=0;y<sz.cy;y++){for(x=0;x<sz.cx;x++){if(pGray[y*sz.cx+x]==128){nHist[pMag[y*sz.cx+x]]++;}}nEdgeNum = nHist[0];nMaxMag = 0;//统计经过“非最大值抑制”后有多少像素for(k=1;k<256;k++){if(nHist[k] != 0){nMaxMag = k;}//梯度为0的点是不可能为边界点的//经过non-maximum suppression后有多少像素nEdgeNum += nHist[k];}//梯度比高阈值*pThrHigh 小的像素点总书目nHighCount = (int)(dRatHigh * nEdgeNum + 0.5);k=1;nEdgeNum = nHist[1];//计算高阈值while((k<(nMaxMag-1)) && (nEdgeNum < nHighCount)){k++;nEdgeNum += nHist[k];}*pThrHigh = k;//低阈值*pThrLow = (int)((*pThrHigh) * dRatLow + 0.5);}//利用函数寻找边界起点void Hysteresis(int *pMag, SIZE sz, double dRatLow, double dRatHigh, LPBYTE pResult) {LONG y,x;int nThrHigh,nThrLow;int nPos;//估计TraceEdge 函数需要的低阈值,以及Hysteresis函数使用的高阈值EstimateThreshold(pMag, sz,&nThrHigh,&nThrLow,pResult,dRatHigh,dRatLow);//寻找大于dThrHigh的点,这些点用来当作边界点,//然后用TraceEdge函数跟踪该点对应的边界for(y=0;y<sz.cy;y++){for(x=0;x<sz.cx;x++){nPos = y*sz.cx + x;//如果该像素是可能的边界点,并且梯度大于高阈值,//该像素作为一个边界的起点if((pResult[nPos]==128) && (pMag[nPos] >= nThrHigh)){//设置该点为边界点pResult[nPos] = 255;TraceEdge(y,x,nThrLow,pResult,pMag,sz);}}}//其他点已经不可能为边界点for(y=0;y<sz.cy;y++){for(x=0;x<sz.cx;x++){nPos = y*sz.cx + x;if(pResult[nPos] != 255){pResult[nPos] = 0;}}}}//根据Hysteresis 执行的结果,从一个像素点开始搜索,搜索以该像素点为边界起点的一条边界的//一条边界的所有边界点,函数采用了递归算法// 从(x,y)坐标出发,进行边界点的跟踪,跟踪只考虑pResult中没有处理并且可能是边界// 点的像素(=128),像素值为0表明该点不可能是边界点,像素值为255表明该点已经是边界点void TraceEdge(int y, int x, int nThrLow, LPBYTE pResult, int *pMag, SIZE sz){//对8邻域像素进行查询int xNum[8] = {1,1,0,-1,-1,-1,0,1};int yNum[8] = {0,1,1,1,0,-1,-1,-1};LONG yy,xx,k;for(k=0;k<8;k++){yy = y+yNum[k];xx = x+xNum[k];if(pResult[yy*sz.cx+xx]==128 && pMag[yy*sz.cx+xx]>=nThrLow ){//该点设为边界点pResult[yy*sz.cx+xx] = 255;//以该点为中心再进行跟踪TraceEdge(yy,xx,nThrLow,pResult,pMag,sz);}}}// Canny算子void Canny(LPBYTE pGray, SIZE sz, double sigma, double dRatLow,double dRatHigh, LPBYTE pResult){//经过高斯滤波后的图像LPBYTE pGaussSmooth;pGaussSmooth = new unsigned char[sz.cx*sz.cy];//x方向导数的指针int *pGradX;pGradX = new int[sz.cx*sz.cy];//y方向int *pGradY;pGradY = new int[sz.cx*sz.cy];//梯度的幅度int *pGradMag;pGradMag = new int[sz.cx*sz.cy];//对原图高斯滤波GaussianSmooth(sz,pGray,pGaussSmooth,sigma);//计算方向导数和梯度的幅度Grad(sz,pGaussSmooth,pGradX,pGradY,pGradMag);//应用非最大抑制NonmaxSuppress(pGradMag,pGradX,pGradY,sz,pResult);//应用Hysteresis,找到所有边界Hysteresis(pGradMag,sz,dRatLow,dRatHigh,pResult);delete[] pGradX;pGradX = NULL;delete[] pGradY;pGradY = NULL;delete[] pGradMag;pGradMag = NULL;delete[] pGaussSmooth;pGaussSmooth = NULL;}/*void CChildWnd::OnCanny(){if (! m_fOpenFile){return;}m_fDone = TRUE;RGBToGray(szImg, aRGB, aGray, BPP);Canny(aGray,szImg,0.1,0.9,0.76,aBinImg);ShowGrayImage("l",szImg,aBinImg);}//*/。
Matlab与VC(MFC)混合编程(介绍Matcom与Matlab 引擎两种方式)文库
本文由wolf1sky贡献doc文档可能在WAP端浏览体验不佳。
建议您优先选择TXT,或下载源文件到本机查看。
Matlab 与 VC 混合编程 1:一、采用 Matcom1、目标1. 测试在 VC 中调用 MatrixC++库,生成矩阵并显示 2. 测试 VC 中调用.m 文件2、步骤2.1 目标 1<1>建立 VC 工程,添加库 v4501v.lib,有两种方法:?向工程中添加文件 v4501v.lib 在 Setting/link 中添加库 v4501v.lib(这样写的前题是 VC 路径设置正确,即在 Options/Directories 中设置,否则请注明详细路径)二者选其一就可以了。
<2> 添加头文件 #include "matlib.h" (这样写的前题是 VC 路径设置正确,即在 Options/Directories 中设置,否则请注明详细路径)建议:最好在工程中把文件 matlib.h 添加进来,方便查看函数详细说明 <3>现在就可以调用 Matrix中的C++函数了,例子如下:// Init matcom initM(MATCOM_VERSION); winaxes(AfxGetMainWnd()->GetSafeHwnd()); Mm a,b; a = (BR(1),2,3,semi,4,5,6,semi,7,8,9); a = transpose(a); b = (BR(1),2,3,semi,4,5,6,semi,7,8,9); m_1.Format("%3f %3f %3f \r\n%3f %3f %3f \r\n%3f %3f %3f \r\n",a.r(1,1),a.r(1,2),a.r(1,3),a.r(2,1),a.r(2,2),a.r(2,3),a.r(3,1),a.r(3,2),a. r(3,3));//m_1 是一个 CEdit 控件 UpdateData(FALSE); exitM();2.2 目标 2<1>首先用 Matlab 调试成功以下两个有依赖关系的.m 文件文件 1:equation.m function y = equation(a,b) y = a * b; 文件 2:CallE.m % function name function [o1,o2] = CallE(x) if (nargin ~= 1) error('arguments must be inputed!'); endif (x == 1) a = reshape(1:9,3,3); elseif (x == 2) a = reshape(11:19,3,3); else error('input error'); end b = magic(3); o1 = equation(a,b); o2 = o1 + 1; <2>将以上两个文件放在同一个目录下,启动 MatCom 编译运行 CallE.m, >> CallE(2) 则在同一目录下生成一个 DEBUG(或者是 Release,在 MatCom 的菜单项 Configuration 中选择)目录下可以找到相应的.cpp 及.h 文件,把它们全部拷贝到 VC 工程目录下,也可以自己建一个文件夹 <3>在 VC 项目中添加这些文件,并在头部添加相应.h 的引用,如下: #include "./matlib/equation.h" #include "./matlib/calle.h" <4>添加调用函数的代码,如下: Mm a,b,c; a = BR(2); 表示输入参数到输出参数的间隔,《MatrixLIB user's 详见calle(a,i_o,b,c); //i_o 是一个间隔符,Guide》m_2.Format("%3f %3f %3f \r\n%3f %3f %3f \r\n%3f \r\n",b.r(1,1),b.r(1,2),b.r(1,3),b.r(2,1),b.r(2,2),b.r(2,3),b.r(3,1),b.r(3,2),b. r(3,3)); %3f %3fUpdateData(FALSE);3、遇到的问题及解决方案<1>当在 VC 工程中添加由 Matcom 转换的 cpp 及 h 文件后,注:如果在编译中出现下列错误:fatal error C1010: unexpected end of file while looking for precompiled headerdirective 解决:进行下列设置:工程->设置-> C/C++ 选择 precompiled headers 选解决:择第一或第二项:自动选择预补偿页眉,如图:<2>使用Matcom 后,生成Debug 版没问题,而生成Release 时链接出错,nafxcw.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in LIBCMT.lib(delete.obj) 解决:解决:将"Project 属性" -> "C/C++" -> "代码生成(codegeneration)" -> "运行时库(run-time library)" 项下修改应用程序的默认标准库版本,我修改成 Debug Multithreads 就可以了,原因是安装Matcom 时库为调试版<3>在其它机器上运行出错解决:解决:将 ago4501.dll v4501v.dll glu32.dll opengl32.dll 附带发布即可 <4>关闭程序后进程没有退出解决:解决:添加语句winaxes(m_hWnd);参考文献1、何东健等.《数字图像处理》.西安电子科技大学出版社.20032、邓科.浅析 VC 与matlab 接口编程(一). VC 知识库,41 期3、邓科.浅析 VC 与 matlab 接口编程(二). VC 知识库,42 期4、Matcom 参考手册Matlab 与 VC 混合编程 2:二、通过 Matlab 引擎与 VC 混合编程--飞狼编程宝典--明明知道选择你是一个错误,却为何那么地坚持这个错误……基于 Matlab 引擎的混合编程方式无法脱离 Matlab 环境,却为何还要使用它?根据本人的实践,对于一般应用,如矩阵运算,图像操作等,使用 Matcom 就已经足够,而且能够脱离 Matlab 那个巨大的环境而独立运行,但是,对于很多好用的 Matlab 工具箱,我们却无法直接在 VC 中调用。
canny算子的matlab程序
canny算子的matlab程序function canny()clcclear allI = imread('lingjian.JPG');%读入图像I=imresize(I,[480,640]);imshow(I);title('原图');I1 = rgb2gray(I);%变换成灰度图像imshow(I1);BW =edge(I1,'canny'); % 调用canny函数figure,imshow(BW); % 显示分割后的图像,即梯度图像title('Canny')[n,m] = size(BW);a_max=40; %a为椭圆长轴,范围需要自己根据图片中的椭圆形状确定a_min=18;b_max=30; %b为椭圆短轴b_min=4;step_a=3; %步长step_b=3;theta_min=-pi/18; %theta倾斜角theta_max=pi/9;step_theta=pi/60;step_angle=2;yz =0.82; %阈值(自己定)size_a = round((a_max-a_min)/step_a)+1;size_b = round((b_max-b_min)/step_b)+1;size_theta=round((theta_max-theta_min)/step_theta)+1;size_angle = round(2*pi/step_angle);hough_space = zeros(m,n,size_a,size_b,size_theta); %设定5维的参数空间并使初值为0[cols,rows] = find(BW); %find—找出非零元素的索引ecount = size(rows);% Hough%图像空间(x,y)对应到参数空间(a,b,p、q、theta)% p = x-a*cos(angle)*cos(theta)+b*sin(angle)*sin(theta)% q = y-a*cos(angle)*sin(theta)-b*sin(angle)*cos(theta)%rows(i)行坐标for i=1:ecount for a=1:size_afor b=1:size_bfor theta=1:size_thetafor k=1:size_angle%hough变换p = round(rows(i)-(a_min+(a-1)*step_a)*cos(k*step_angle)*cos(theta_min+(theta-1)*step_theta)+(b_min+(b-1)*step_b)*sin(k*step_angle)*sin(theta_min+(theta-1)*step_theta));q = round(cols(i)-(a_min+(a-1)*step_a)*cos(k*step_angle)*sin(theta_min+(theta-1)*step_theta)-(b_min+(b-1)*step_b)*sin(k*step_angle)*cos(theta_min+(theta-1)*step_theta));if(p>0&p<=m&q>0&q<=n)hough_space(p,q,a,b,theta) = hough_space(p,q,a,b,theta)+1;endendendendendend% 搜索超过阈值的聚焦点max_para = max(max(max(max(max(hough_space)))));index = find(hough_space>max_para*yz); %find—找出hough_space中大于阈值的缩引并存入 indexlength = size(index);hough_circle1=zeros(m,n); %确定为椭圆上的点的坐标hough_circle2=zeros(m,n);%找出峰值对应的参数空间坐标for k=1:lengthpar5 = floor((index(k)-1)/(m*n*size_a*size_b))+1; %theta增量par4 = floor((index(k)-(par5-1)*(m*n*size_a*size_b))/(m*n*size_a))+1; %b增量par3 = floor((index(k)-(par5-1)*(m*n*size_a*size_b)-(par4-1)*(m*n*size_a))/(m*n))+1; %a 增量par2 = floor((index(k)-(par5-1)*(m*n*size_a*size_b)-(par4-1)*(m*n*size_a)-(par3-1)*(m*n))/m)+1; %p增量par1 = index(k)-(par5-1)*(m*n*size_a*size_b)-(par4-1)*(m*n*size_a)-(par3-1)*(m*n)-(par2-1)*m; %q增量par5=theta_min+(par5-1)*step_theta;par4 = b_min+(par4-1)*step_b;par3 = a_min+(par3-1)*step_a;theta(k)=par5;b(k)=par4;a(k)=par3;q(k)=par2;p(k)=par1;end%求出两圆参数平均值[row1 col1]=size(p);count=1;theta=sort(theta);p=sort(p);q=sort(q);a=sort(a);b=sort(b);THETA(count)=theta(1);P(count)=p(1);A(count)=a(1);B(count)=b(1);Q(count)=q(1);for t=1:1:col1if abs(P(count)-p(t))<=10THETA(count)=(theta(t)+THETA(count))/2; A(count)=(a(t)+A(count))/2;B(count)=(b(t)+B(count))/2;P(count)=(p(t)+P(count))/2;Q(count)=(q(t)+Q(count))/2;elsecount=count+1;THETA(count)=theta(t);A(count)=a(t);B(count)=b(t);P(count)=p(t);Q(count)=q(t);endendTHETAABPQ%绘制椭圆TYZ=zeros(1,2);TYY=zeros(1,2);ct_z=1;ct_y=1;for i=1:ecountif round(((rows(i)-P(1))*cos(THETA(1))+(cols(i)-Q(1))*sin(THETA(1)))^2/(A(1)^2)+(-(rows(i)-P(1))*sin(THETA(1))+(cols(i)-Q(1))*cos(THETA(1)))^2/(B(1)^2))<1.5 ...&round(((rows(i)-P(1))*cos(THETA(1))+(cols(i)-Q(1))*sin(THETA(1)))^2/(A(1)^2)+(-(rows(i)-P(1))*sin(THETA(1))+(cols(i)-Q(1))*cos(THETA(1)))^2/(B(1)^2))>0.5TYY(ct_y,1)=rows(i);TYY(ct_y,2)=cols(i);hough_circle1(cols(i),rows(i))=1;ct_y=ct_y+1;endif round(((rows(i)-P(2))*cos(THETA(2))+(cols(i)-Q(2))*sin(THETA(2)))^2/(A(2)^2)+(-(rows(i)-P(2))*sin(THETA(2))+(cols(i)-Q(2))*cos(THETA(2)))^2/(B(2)^2))<1.5 ...&round(((rows(i)-P(2))*cos(THETA(2))+(cols(i)-Q(2))*sin(THETA(2)))^2/(A(2)^2)+(-(rows(i)-P(2))*sin(THETA(2))+(cols(i)-Q(2))*cos(THETA(2)))^2/(B(2)^2))>0.5TYZ(ct_z,1)=rows(i);TYZ(ct_z,2)=cols(i);hough_circle2(cols(i),rows(i))=1;ct_z=ct_z+1;endendfigureimshow(hough_circle1),title('hough圆1')figureimshow(hough_circle2),title('hough圆2')%分别计算两个椭圆的参数[row_TYZ,col_TYZ]=size(TYZ);for i1=1:1:row_TYZWTZ(i1,:)=[TYZ(i1,1)^2 TYZ(i1,1)*TYZ(i1,2) TYZ(i1,2)^2 TYZ(i1,1) TYZ(i1,2) 1; ];end[v_z1,d_z1]=svd(WTZ'*WTZ);v_z1=vpa(v_z1,8)d_z1=double(d_z1);[row_TYY,col_TYY]=size(TYY);for j1=1:1:row_TYYWTY(j1,:)=[TYY(j1,1)^2 TYY(j1,1)*TYY(j1,2) TYY(j1,2)^2 TYY(j1,1) TYY(j1,2) 1; ];end[v_y1,d_y1]=svd(WTY'*WTY);v_y1=vpa(v_y1,8)d_y1=double(d_y1);。
matlab与vc混编
matlab与vc混编matlab与vc混编-概述篇--转贴自pris学术论坛第一章、详述...第一章、概述matlab就是当今世界上采用最为广为的数学软件,它具备相当强悍的数值排序、数据处理、系统分析、图形表明,甚至符号运算功能,就是一个完备的数学平台,在这个平台上,你只需寥寥数语就可以顺利完成十分复杂的功能,大大提高了工程分析排序的效率。
另外由于matlab的广为采用,于是发生了向各个领域专门采用的工具箱(即为在某一研究领域常用数学工具的函数纸盒),这些工具箱的发生更加推动了matlab的盛行。
matlab强大的功能只能在它所提供的平台上才能使用,也就是说,你必需在安装有matlab系统的机器上采用.m文件,这样就给工程排序增添了非常大不便;特别就是,在matlab中,并使用的行解释方式执行代码,这样大大地限制了代码执行速度。
于是人们想到,能否开发一个matlab与其他高级语言的USB,这样就可以把matlab的强悍功能带入各种应用程序中,并且通过高级语言编译器编译为2进制代码,从而大大提高了执行速度。
1.用matlab的mcc将.m文件翻译为cpp源文件,然后在c编译器中调用也可以用mcc编程编程为stand-alone程序。
是我最喜欢用的方法。
方法1和2/3各有利弊,1不积极支持图形(积极支持图形的库国内现在还没d),1对类积极支持也比较,2积极支持绝大多数的matlab语句(包含图形),但对于struct等的积极支持也有缺陷。
vc++中使用matlab的c++数学库和mcc生成的程序0、概述matlab5.3的提供了c/c++数学库,其中的c++数学库功能很强,使用它可以用类似matlab的语法编写c++程序,十分方便。
虽然速度上仍然比手工c/c++程序慢,但是由此换来的高效的开发效率和可靠性往往是值得的。
另外mcc命令可以将m文件转化为c或cpp文件,编译后可以脱离matlab运行,它们也是使用的c/c++数学库。
vc和matlab的混合编程-Silence的日志-网易博客
vc和matlab的混合编程-Silence的日志-网易博客vc和matlab的混合编程技术 2008-10-29 23:14:29 阅读60 评论0 字号:大小订阅matlab真的是一个好东西,它的介绍我就不说啦,自己google 去,matlab在数学处理、数字图像方面的研究有很好的应用,只是他在与其他例如vc,vb,java的接合上显得比较的困难,似乎大家都在探讨这方面的问题,经过这些天的猛看猛试验,最终在matlab的COM接合上实现突破,并且正如matlab推荐的那样,真的非常的方便和通用,几乎可以处理所有的函数,包括图形图像的处理函数。
一般来说,vc调用matlab混合编程有以下几个途径:一、通过Matlab Engine方式Matlab Engine是指一组Matlab提供的接口函数,支持C语言, Matlab Engine采用C/S(客户机/服务器)模式,Matlab作为后台服务器,而C程序作为前台客户机,通过Windows的动态控件与服务器通信,向Matlab Engine传递命令和数据信息,从Matlab Engine接受数据信息。
用户可以在前台应用程序中调用这些接口函数,实现对Matlab Engine的控制。
采用这种方法几乎能利用Matlab全部功能,但是需要在机器上安装Matlab软件,而且执行效率低,因此在实际应用中不采用这种方法,在软件开发中也不可行,我认为适合个人使用或做演示用,因此不打算介绍。
二、直接调用Matlab的C/C++数学函数库Matlab中提供了可以供C/C++语言调用的C/C++数学函数库,其中包含了大量用C\C++语言重新编写的Matlab数学函数,这些函数涉及到线形代数、数值分析、傅立叶变换、多项式计算、解微分方程等,并且函数库中提供了大量各种矩阵操作函数,在VC中可以直接使用这些函数,通过这些函数可以在VC中方便的实现在Matlab中矩阵运算功能。
MATLAB与VC混合编程.
MATLAB 与 VC 混合编程SCIE摘要:MATLAB 提供了很丰富的编程接口,可以通过这些接口使用其它语言来编写模块集成到 MATLAB 程序中,也可以在其它程序设计语言中调用 MATLAB 。
尽管如此,在某些情况下可能仍然不能满足某些特殊的要求, 本文从实际应用出发, 介绍了 MATLAB 与 VC 混合编程的一些方法。
需要特别说明的是:本文内容是针对MATLAB6.5和 VC6.0的,并不适应于其它版本的 MATLAB 。
关键词:混合编程 MATLAB VC 窗口嵌入一、 VC中使用编译得到的 C++源程序文件通过 MATLAB 的编译器我们可以将 m 代码编译为独立的可执行程序,从而达到脱离 MATLAB 、在未安装 MATLAB 的计算机上发布的目的。
但是这样做仍然不能满足如下要求: MATLAB设计的图形用户界面功能还不够强大,不支持表格、目录树以及分组单选按钮等控件;当在一个 GUI 中放置过多的控件时,速度会比较慢。
整个软件并不是以 MATLAB 为主开发的,需要把 MATLAB 编写的代码融合到软件主体中,而不是生成独立的程序。
需要修改 MALTAB 编译器自动生成的代码, 或在其中添加代码以实现特定的功能。
将 m 文件编译生成 C 或者 C ++代码,在 VC 中使用这些代码,就可以解决以上几个或者更多的问题。
在此之前,需要对 VC 的开发环境进行设置,添加MATLAB 的 Include 目录和 Library 目录,操作如下:启动 VC ,点击菜单 Tools-Options ,出现如下对话框:图表 1设置 Include 目录¾在 Show directories for下方的下拉框中选择 Include files,在 Directories 下方列表框的空白一行或者单击 Directories 右方的左起第一个按钮, 添加如下两个目录: $matlabroot\extern\include\cpp$matlabroot\extern\include¾在 Show directories for下方的下拉框中选择 Include files,在 Directories 下方列表框的空白一行或者单击 Directories 右方的左起第一个按钮, 添加如下两个目录: $matlabroot\extern\include\cpp$matlabroot\extern\include其中 $matlabroot为 MATLAB 的安装目录,如图表 2所示。
matlab与C混合编程步骤详解
1MATLAB Compiler 是MATLAB自带的一个编译器,它能将m文件转化成 C、C++或p等各种类型的源代码,并根据需要生成可执行文件、lib文件(库文件)、dll文件或S函数文件等。
Matlab所使用的编译器包括了MATLAB 的C\C++数学库函数以及图形库。
必须保证编译器的正确配置,因为编译器使用了C\C++库函数,所以在使用前需要使用mex -setup 和 mbuild -setup两个命令对编译器进行配置。
步骤如下:1. 设置Matlab的编译器,使用外部的VC或者gcc等编译器。
2. 编译m文件成dll3. 设置VC等的继承环境,设置C需要用到的静态库和动态库4. 编写C调用dll1.1设置MATLAB编译器首先要安装Matlab 编译器,一般来说,在安装了Matlab后编译器就己经安装了,所在就只需要对Matlab编译器进行设置。
1.1.1 编译环境设置首先设置系统的环境变量,点击“我的电脑”属性-→系统特性--→高级-→环境变量-→添加系统变量Matlab值为Matlab的安装路径:G:\matlab7.0\bin\win32,重启电脑即可。
1.1.2 MATLAB7.0 编译器设置(a) 为编译后产生的MEX文件进行预配置在Matlab 的命令窗口(Command Window) 键入“mex -setup ”命令后,按回车键,安装Matlab 编译器;(b) 为产生独立外部应用程序进行预配置对Matlab编译器mbuild应用程序进行设置,运行Matlab ,在Matlab 的命令窗口(Command Window) 键入“mbuild -setup ”命令后,按回车键,安装Matlab 编译器;1.2 将MATLAB函数转成DLL函数在Matlab的Command Window /下输入命令:命令 1 :mcc -W lib:dlltest -T link:lib huatu_test.m或命令 2 :mcc -W cpplib: dlltest -T link:lib huatu_test.m命令1生成的是C,命令2生产的是C++。
VC+matlab联合编译
VS2005如何调用Matlab7定义的.m文件中的函数以一个简单的例子来说明一下如果在VC中调用matlab中定义的.m文件. 与Matlab6.5稍有不同。
(一)先建立matlab的m文件这里为了简单起见,我在matlab中定义了一个求和函数,其m文件如下:function y = add_zh(a,b)y=a+b保存为myadd.m(二)对matlab编译环境进行设置为操作系统添加环境变量:在环境变量(我的电脑->右键->高级)path中加入<MATLAB7_root>\bin\win32打开matlab,在命令行状态下键入:mex -setup然后出现如下提示:--------------------------------------------------------------------------------------Select a compiler:[1] Intel C++ 9.1 (with Microsoft Visual C++ 2005 SP1 linker)[2] Intel Visual Fortran 10.1 (with Microsoft Visual C++ 2005 SP1 linker)[3] Intel Visual Fortran 9.1 (with Microsoft Visual C++ 2005 SP1 linker)[4] Lcc-win32 C 2.4.1[5] Microsoft Visual C++ 6.0[6] Microsoft Visual C++ .NET 2003[7] Microsoft Visual C++ 2005 SP1[8] Microsoft Visual C++ 2008 Express[9] Microsoft Visual C++ 2008 SP1[10] Open WATCOM C++[0] NoneCompiler:--------------------------------------------------------------------------------------这里我们选择'7’。
matlab与vc混合编程(绝对无误)
matlab与vc混合编程1、环境设置在桌面上右键单击“我的电脑”图标出现以下菜单单击“属性”菜单项,出现“系统特性”对话框,单击“高级”选项卡,如下图所示在上图中,单击“环境变量”按钮,出现“环境变量”对话框,添加系统变量 matlab 值为 D:\MATLAB 即 matlab 的安装路径,如下图所示在环境变量 path 中加入 D:\MATLAB\bin\win32 ,如下图所示按“确定”完成设置后,重启计算机或注销当前用户,即可应用新设置。
2、matlab 编译器设置(1) mex 命令设置(a) 运行 matlab ,在 matlab 的命令窗口 (Command Window) 键入“ mex -setup ”命令后,按回车键,安装 matlab 编译器;(b) 命令窗口出现如下提示mex -setupPlease choose your compiler for building external interface (MEX) files:Would you like mex to locate installed compilers [y]/n?此时键入”y”,按回车;(c) 命令窗口出现如下提示Select a compiler:[1] Digital Visual Fortran version 6.0 in C:\Program Files\Microsoft Visual Studio[2] Lcc C version 2.4.1 in D:\MATLAB\sys\lcc[3] Microsoft Visual C/C++ version 6.0 in C:\Program Files\Microsoft Visual Studio[4] Open WATCOM C/C++ version 1.3 in D:\Maple11[0] None此时键入”3”,按回车;选择 Microsoft Visual C++6.0 的编译器(d) 命令窗口出现如下提示Please verify your choices:Compiler: Microsoft Visual C/C++ 6.0Location: C:\Program Files\Microsoft Visual StudioAre these correct?([y]/n):此时键入”y”,按回车;确认选择 Microsoft Visual C++6.0 的编译器(2) mbuild 命令设置(a) 运行 matlab ,在 matlab 的命令窗口 (Command Window) 键入“ mbuild -setup ”命令后,按回车键,安装 matlab 编译器;(b) 命令窗口出现如下提示mbuild -setupPlease choose your compiler for building standalone MA TLAB applications:Would you like mbuild to locate installed compilers [y]/n?此时键入”y”,按回车;(c) 命令窗口出现如下提示Select a compiler:[1] Lcc C version 2.4.1 in D:\MATLAB\sys\lcc[2] Microsoft Visual C/C++ version 6.0 in C:\Program Files\Microsoft Visual Stu dio[0] None此时键入”2”,按回车;选择 Microsoft Visual C++6.0 的编译器(d) 命令窗口出现如下提示Please verify your choices:Compiler: Microsoft Visual C/C++ 6.0Location: C:\Program Files\Microsoft Visual StudioAre these correct?([y]/n):此时键入”y”,按回车,确认选择 Microsoft Visual C++6.0 的编译器,编译器设置完成。
浅析VC与Matlab联合编程(二)
::首页>> 文档中心>> 在线杂志>> 其它[ 在线杂志第42期][ 原创文档本文适合中级读者已阅读231次]浅析VC与Matlab联合编程(二)作者:邓科下载源代码在“浅析VC与Matlab联合编程(一)”中简单介绍了VC与matcom的接口编程,实现本功能,要真正熟练使用接口编程,还要对函数调用有一定了解。
本文通过一个实例,较详细的介编译后的函数。
首先新建一个函数huatu.m,该函数的功能是:接受用户输入的左端点值和右端点值两个输图形。
函数还将生成两个随机数,作为一个点的坐标在图中打印出来(绿点),用来说明如何在步骤如下:1.建立一个名为Example2基于对话框的MFC(exe)工程。
2.在matcom中新建一个名为huatu.m文件,如图1;图13.在matcom命令窗口中运行该函数,如图2;图24.将生成的huatu.h、huatu.cpp(默认位置为安装目录:\matcom45\samples\Debug)和ma 为安装目录:\matcom45\lib)四个文件拷贝到建立的工程Example2目录下。
5.将第四步拷贝的四个文件加入到VC工程中:工程->添加工程->文件,选择刚才拷贝到Exa 成后如图3;图36.在Example2dlg.cpp中添加头文件:(如图4所示)#include "matlib.h"#include "huatu.h"图47.为工程建立界面:添加一个Button按扭控件;添加四个Edit box控件,用于显示数据;添加显示文字,一个显示图形,将显示图形的Static text的ID设置为ID_PIC。
其他所有控件属性保适当调整显示图形Static text控件的边缘)。
如图5所示图58.按Ctrl+W为控件添加变量。
如图6所示图69.为Button1按钮添加响应代码。
如图7所示图710.运行程序,输入左端点和右端点,点击”画图”按钮,结果如图8所示。
Canny算子提取边缘Matlab源代码
Canny算子提取边缘Matlab源代码介绍function e=canny_edge(I,sigma)%functione=edge(I,'canny',thresh,sigma);%该函数实现Canny算子提取边缘点%输入图像为I,标准差sigma,输出为边缘图像e[m,n]=size(I);Rr=2:m-1;cc=2:n-1;e=repmat(logical(uint8(0)),m,n);%产生同样大小的边缘图像e,初始化为1 ,即初始化边缘GaussianDieOff=-0.001;%设定高斯函数消失门限PercentOfPixelsNotEdges=-7;%用于计算边缘门限ThresholdRatio=-4;%设置两个门限的比例%首先设计高斯滤波器和它的微分pw=1:30;%设定滤波器宽度ssq=sigma*sigma;%计算方差width=max(find(exp(-(pw.*pw)/(2*sigma*sigma))>GaussianDieOff)); %计算滤波算子宽度t=(-width:width);len=2*width+1;t3=[t-.5;t;t+.5];%对每个像素左右各半个像素位置的值进行平均gau=sum(exp(-(t3.*t3)/(2*ssq))).'/(6*pi*ssq);%一维高斯滤波器dgau=(-t.*exp(-(t.*t)/(2*ssq))/ssq).';%高斯滤波器的微分ra=size(I,1);ca=size(I,2);ay=255*double(I);ax=255*double(I');h=conv(gau,dgau);%利用高斯函数滤除噪声和用高斯算子的一阶微分对图像滤波合并为一个算子ax=conv2(ax,h,'same').';%产生x方向滤波ay=conv2(ay,h,'same');%产生y方向滤波mag=sqrt((ax.*ax)+(ay.*ay));%计算滤波结果的幅度magmax=max(mag(:));if magmax>0mag=mag/magmax;%对滤波幅度进行归一化end%下面根据滤波幅度的概率密度计算滤波门限[counts,x]=imhist(mag,64);%计算滤波结果的幅度的直方图highThresh=min(find(cumsum(counts)>PercentOfPixelsNotEdges*m*n))/64; %通过设定非边缘点的比例来确定高门限lowThresh=ThresholdRatio*highThresh;%设置低门限为高门限乘以比例因子thresh=[lowThresh,highThresh];%下面进行非极大抑制%大于高门限的点归于强边缘图像%小于低门限的点归于弱边缘图像idxStrong=[];for dir=1:4idxLocalMax=cannyFindLocalMaxima(dir,ax,ay,mag); idxWeak=idxLocalMax(mag(idxLocalMax)>lowThresh);e(idxWeak)=1;idxStrong=[idxStrong;idxWeak(mag(idxWeak)>highThresh)]; endrstrong=rem(idxStrong-1,m)+1;%rem是求余数cstrong=floor((idxStrong-1)/m)+1;%向-∞取整e=bwselect(e,cstrong,rstrong,8);%通过形态学算子将两幅图像的边缘进行连接(资料素材和资料部分来自网络,供参考。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
VC调用matlab图像处理工具箱进行canny边缘检测
作者:bugzhao 注意:本程序基于VC6+Matlab7环境
Matlab是一款可视化科学计算软件,内置了大量工具箱函数,支持完善的矩阵运算,并且可以可视化的显示计算结果。
有时候我们在VC编程的时候需要调用Matlab内置的矩阵运算函数,或者工具箱函数,这样会大大加速我们软件开发的速度,同时基于Matlab的运算也更加稳定。
这里讲述一下 edge(im,’canny’) 这个matlab里面的image processing toolbox 的函数如何在VC里被调用的方法。
为了让更多的初学者可以理解,我采用了step-by-step的方法,只要按照文中方法一步步去做,肯定可以成功的。
至于更多其他的细节问题,大家可以看Matlab关于compiler的帮助。
首先来看看环境的设置。
环境的设置只须一次,以后再用就不必设了。
Matlab7默认没有按照MCR,首先我们要安装之。
其安装文件路径一般在:C:\MATLAB7\toolbox\compiler\deploy\win32\MCRInstaller.exe
找到这个文件双击既可安装。
接下来要设置VC中的路径。
两个地方都要设,如下所示:
以上工作完成之后,下面还要来设置编译器的链接选项。
注意此步每次都要设置的。
在link文件中输入:
mclmcr.lib libmat.lib libmex.lib libmx.lib libeng.lib
如图所示:
接下来开始编写程序。
这里我采用了自己以前编写的一个图像处理仿真平台Imagedemo,可以对256级灰度图像进行各种运算。
设计界面如下:
我将菜单响应函数编写在文件:ImagedemoView.CPP中。
在我们编写程序调用matlab之前,还要在该文件的头部加入头文件的声明如下:
#include "mclmcr.h"
#include "matrix.h"
#include "mat.h"
#include "engine.h"
接下来编写菜单响应代码。
先看看代码,我再把主要函数讲解一下。
//调用matlab图像处理工具箱的canny边缘检测
void CImgDemoView::Oncalliptoolboxcanny()
{
i,j;
int
unsigned char *lpSrc;
CImgDemoDoc* pDoc = GetDocument();
ASSERT_V ALID(pDoc);
if(pDoc->m_hDIB == NULL)
;
return
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->m_hDIB);
LPSTR lpDIBBits=::FindDIBBits (lpDIB);
//读取图像宽高
int cxDIB = (int) ::DIBWidth(lpDIB); // Size of DIB - x
int cyDIB = (int) ::DIBHeight(lpDIB); // Size of DIB - y
long lLineBytes = WIDTHBYTES(cxDIB * 8); // 计算图像每行的字节数 //分配一临时存储空间
unsigned char * temp=new unsigned char[cxDIB*cyDIB*sizeof(unsigned char)];
//先将图像读入临时缓冲区temp以便于后期送入matlab引擎进行处理
//每行
for(i = 0; i < cyDIB; i++)
{
每列
//
for(j = 0; j < cxDIB; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (cyDIB - 1 - i) + j;
temp[j*cyDIB+i]=(*lpSrc);
}
}
mclInitializeApplication(NULL,0);
//定义matlab可以识别的矩阵作为输入和输出
mxArray * input=NULL,* output=NULL;
//为其分配内存空间
input=mxCreateNumericMatrix(cyDIB,cxDIB,mxUINT8_CLASS,mxREAL);
output=mxCreateNumericMatrix(cyDIB,cxDIB,mxUINT8_CLASS,mxREAL);
//将temp区数据赋给matlab可以识别的矩阵形式
memcpy((unsigned char *)mxGetPr(input),(unsigned char
*)temp,cxDIB*cyDIB*sizeof(unsigned char));
//打开matlab引擎
*ep;
Engine
ep=engOpen(NULL);
//将输入input和输出output与matlab中变量关联
engPutVariable(ep,"input",input);
//调用matlab工具箱函数进行canny边缘检测
//注意要使用im2uint8将二值边缘图像转换为uint8格式
engEvalString(ep,"output=edge(input,'canny');output=im2uint8(output);");
output=engGetVariable(ep,"output");//提取变量
//将边缘检测的结果传回临时缓存区temp
char
*)temp,(unsigned char
memcpy((unsigned
*)mxGetPr(output),cxDIB*cyDIB*sizeof(unsigned char));
//将临时缓冲区temp数据写入图像
//每行
for(i = 0; i < cyDIB; i++)
{
每列
//
for(j = 0; j < cxDIB; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (cyDIB - 1 - i) + j;
(*lpSrc)=temp[j*cyDIB+i];
}
}
//释放内存
input=0;
mxDestroyArray(input);
mxDestroyArray(output); output=0;
mclTerminateApplication();
//关闭引擎
engClose(ep);
//刷新客户区
::GlobalUnlock((HGLOBAL)
pDoc->m_hDIB);
Invalidate(TRUE);
}
代码的编写思路如下:首先获取当前文档,然后获得图像的指针和宽、高等信息;然后将图像像素数据赋值到一个缓冲区内存放;然后把此缓冲区内的数据传递给mxArray格式的内存空间。
接下来打开engine,把mxArray格式的数据跟engine工作区中的变量相联合。
到此,我们就可以利用engEvalString来调用matlab的各种函数来进行计算了。
计算过后,把工作区的变量取出来放入mxArray 格式的内存空间内,然后再将其存入缓存区,最终写入图像像素空间,从而完成整个过程。
具体的讲解可以看看上面代码的注释,配合matlab帮助,相信可以很快成功的。
边缘检测的结果如下:
源代码及说明文档下载:/
作者:bugzhao
山东大学 2005年3月30日。