2016-12-19 16:29:59 hujiameihuxu 阅读数 990
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4245 人正在学习 去看看 贾志刚

1 %% 第9章 形态学处理 2 3 %% imdilate膨胀 4 clc 5 clear 6 7 A1=imread('.\images\dipum_images_ch09\Fig0906(a)(broken-text).tif'); 8 info=imfinfo('.\images\dipum_images_ch09\Fig0906(a)(broken-text).tif') 9 B=[0 1 0 10 1 1 1 11 0 1 0]; 12 A2=imdilate(A1,B);%图像A1被结构元素B膨胀 13 A3=imdilate(A2,B); 14 A4=imdilate(A3,B); 15 16 subplot(221),imshow(A1); 17 title('imdilate膨胀原始图像'); 18 19 subplot(222),imshow(A2); 20 title('使用B后1次膨胀后的图像'); 21 22 subplot(223),imshow(A3); 23 title('使用B后2次膨胀后的图像'); 24 25 subplot(224),imshow(A4); 26 title('使用B后3次膨胀后的图像'); 27%imdilate图像膨胀处理过程运行结果如下:

 28 
 29 %% imerode腐蚀
 30 clc
 31 clear
 32 A1=imread('.\images\dipum_images_ch09\Fig0908(a)(wirebond-mask).tif');
 33 subplot(221),imshow(A1);
 34 title('腐蚀原始图像');
 35 
 36 %strel函数的功能是运用各种形状和大小构造结构元素
 37 se1=strel('disk',5);%这里是创建一个半径为5的平坦型圆盘结构元素
 38 A2=imerode(A1,se1);
 39 subplot(222),imshow(A2);
 40 title('使用结构原始disk(5)腐蚀后的图像');
 41 
 42 se2=strel('disk',10);
 43 A3=imerode(A1,se2);
 44 subplot(223),imshow(A3);
 45 title('使用结构原始disk(10)腐蚀后的图像');
 46 
 47 se3=strel('disk',20);
 48 A4=imerode(A1,se3);
 49 subplot(224),imshow(A4);
 50 title('使用结构原始disk(20)腐蚀后的图像');
 51 %图像腐蚀处理过程运行结果如下:
 52 
 53 %% 开运算和闭运算
 54 clc
 55 clear
 56 f=imread('.\images\dipum_images_ch09\Fig0910(a)(shapes).tif');
 57 %se=strel('square',5');%方型结构元素
 58 se=strel('disk',5');%圆盘型结构元素
 59 imshow(f);%原图像
 60 title('开闭运算原始图像')
 61%运行结果如下:

 62 
 63 %开运算数学上是先腐蚀后膨胀的结果
 64 %开运算的物理结果为完全删除了不能包含结构元素的对象区域,平滑
 65 %了对象的轮廓,断开了狭窄的连接,去掉了细小的突出部分
 66 fo=imopen(f,se);%直接开运算
 67 figure,subplot(221),imshow(fo);
 68 title('直接开运算');
 69 
 70 %闭运算在数学上是先膨胀再腐蚀的结果
 71 %闭运算的物理结果也是会平滑对象的轮廓,但是与开运算不同的是,闭运算
 72 %一般会将狭窄的缺口连接起来形成细长的弯口,并填充比结构元素小的洞
 73 fc=imclose(f,se);%直接闭运算
 74 subplot(222),imshow(fc);
 75 title('直接闭运算');
 76 
 77 foc=imclose(fo,se);%先开后闭运算
 78 subplot(223),imshow(foc);
 79 title('先开后闭运算');
 80 
 81 fco=imopen(fc,se);%先闭后开运算
 82 subplot(224),imshow(fco);
 83 title('先闭后开运算');
 84%开闭运算结果如下:

 85 
 86 %先膨胀再腐蚀
 87 fse=imdilate(f,se);%膨胀
 88 
 89 %gcf为得到当前图像的句柄,当前图像是指例如PLOT,TITLE,SURF等
 90 %get函数为得到物体的属性,get(0,'screensize')为返回所有物体screensize属性值
 91 %set函数为设置物体的属性
 92 figure,set(gcf,'outerposition',get(0,'screensize'));%具体目的是设置当前窗口的大小
 93 subplot(211),imshow(fse);
 94 title('使用disk(5)先膨胀后的图像');
 95 
 96 fes=imerode(fse,se);
 97 subplot(212),imshow(fes);
 98 title('使用disk(5)先膨胀再腐蚀后的图像');
 99%先膨胀后腐蚀图像如下:

100 
101 %先腐蚀再膨胀
102 fse=imerode(f,se);
103 figure,set(gcf,'outerposition',get(0,'screensize'))
104 subplot(211),imshow(fse);
105 title('使用disk(5)先腐蚀后的图像');
106 
107 fes=imdilate(fse,se);
108 subplot(212),imshow(fes);
109 title('使用disk(5)先腐蚀再膨胀后的图像');
110%先腐蚀后膨胀的图像如下:

111 
112 %% imopen imclose在指纹上的应用
113 clc
114 clear
115 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif');
116 se=strel('square',3);%边长为3的方形结构元素
117 subplot(121),imshow(f);
118 title('指纹原始图像');
119 
120 A=imerode(f,se);%腐蚀
121 subplot(122),imshow(A);
122 title('腐蚀后的指纹原始图像');
123%指纹原始图像和腐蚀后的图像结果如下:

124 
125 fo=imopen(f,se);
126 figure,subplot(221),imshow(fo);
127 title('使用square(3)开操作后的图像');
128 
129 fc=imclose(f,se);
130 subplot(222),imshow(fc);
131 title('使用square闭操作后的图像');
132 
133 foc=imclose(fo,se);
134 subplot(223),imshow(foc);
135 title('使用square(3)先开后闭操作后的图像')
136 
137 fco=imopen(fc,se);
138 subplot(224),imshow(fco);
139 title('使用square(3)先闭后开操作后的图像');
140%指纹图像开闭操作过程结果如下:

141 
142 %% bwhitmiss击中或击不中变换
143 clc
144 clear
145 f=imread('.\images\dipum_images_ch09\Fig0913(a)(small-squares).tif');
146 imshow(f);
147 title('击中或不击中原始图像');
148%击中或不击中原始图像显示结果如下:

149 
150 B1=strel([0 0 0;0 1 1;0 1 0]);%击中:要求击中所有1的位置
151 B2=strel([1 1 1;1 0 0;1 0 0]);%击不中,要求击不中所有1的位置
152 B3=strel([0 1 0;1 1 1;0 1 0]);%击中
153 B4=strel([1 0 1;0 0 0;0 0 0]);%击不中
154 B5=strel([0 0 0;0 1 0;0 0 0]);%击中
155 B6=strel([1 1 1;1 0 0;1 0 0]);%击不中
156 
157 g=imerode(f,B1)&imerode(~f,B2)%利用定义来实现击中或击不中
158 figure,subplot(221),imshow(g);
159 title('定义实现组1击中击不中图像');
160 
161 g1=bwhitmiss(f,B1,B2);
162 subplot(222),imshow(g1);
163 title('结构数组1击中击不中后的图像');
164 
165 g2=bwhitmiss(f,B3,B4);
166 subplot(223),imshow(g2);
167 title('结构数组2击中击不中的图像');
168 
169 g3=bwhitmiss(f,B5,B6);
170 subplot(224),imshow(g3);
171 title('结构数组3击中击不中的图像');
172%击中击不中变换后图像如下:

173 
174 %%makelut
175 clc
176 clear
177 
178 f=inline('sum(x(:))>=3');%inline是用来定义局部函数的
179 lut2=makelut(f,2)%为函数f构造一个接收2*2矩阵的查找表
180 lut3=makelut(f,3)
181 
182 %% Conway生命游戏
183 clc
184 clear
185 lut=makelut(@conwaylaws,3);
186 bw1=  [0     0     0     0     0     0     0     0     0     0
187        0     0     0     0     0     0     0     0     0     0
188        0     0     0     1     0     0     1     0     0     0
189        0     0     0     1     1     1     1     0     0     0
190        0     0     1     0     0     0     0     1     0     0
191        0     0     1     0     1     1     0     1     0     0
192        0     0     1     0     0     0     0     1     0     0
193        0     0     0     1     1     1     1     0     0     0
194        0     0     0     0     0     0     0     0     0     0
195        0     0     0     0     0     0     0     0     0     0  ];
196 subplot(221),imshow(bw1,'InitialMagnification','fit');
197 title('Generation 1');
198 
199 bw2=applylut(bw1,lut);
200 subplot(222),imshow(bw2,'InitialMagnification','fit'),
201 title('Generation 2');
202 
203 bw3=applylut(bw2,lut);
204 subplot(223),imshow(bw3,'InitialMagnification','fit');
205 title('Generation 3');
206 
207 temp=bw1;
208 for i=2:100
209     bw100=applylut(temp,lut);
210     temp=bw100;
211 end
212 subplot(224),imshow(bw100,'InitialMagnification','fit')
213 title('Generation 100');
214%显示Generation结果如下:

215 
216 %% getsequence
217 clc
218 clear
219 se=strel('diamond',5)
220 decomp=getsequence(se)%getsequence函数为得到分解的strel序列
221 decomp(1)
222 decomp(2)
223 
224 %% endpoints
225 clc
226 clear
227 
228 f1=imread('.\images\dipum_images_ch09\Fig0914(a)(bone-skel).tif');
229 subplot(121),imshow(f1);
230 title('原始形态骨架图像');
231 
232 g1=endpoints(f1);
233 %set(gcf,'outerposition',get(0,'screensize'));%运行完后自动生成最大的窗口
234 subplot(122),imshow(g1);
235 title('骨架图像的端点图像');
236 %骨架头像端点检测头像如下:
237 
238 f2=imread('.\images\dipum_images_ch09\Fig0916(a)(bone).tif');
239 figure,subplot(121),imshow(f2);
240 title('原始骨头图像');
241 
242 g2=endpoints(f2);
243 subplot(122),imshow(g2);
244 title('骨头图像端点头像');%结果是没有端点
245%骨头头像端点检测图像如下:

246 
247 %% bwmorph组合常见形态学之细化
248 clc
249 clear
250 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif');
251 subplot(221),imshow(f);
252 title('指纹图像细化原图');
253 
254 g1=bwmorph(f,'thin',1);
255 subplot(222),imshow(g1);
256 title('指纹图像细化原图');
257 
258 g2=bwmorph(f,'thin',2);
259 subplot(223),imshow(g2);
260 title('指纹图像细化原图');
261 
262 g3=bwmorph(f,'thin',Inf);
263 subplot(224),imshow(g3);
264 title('指纹图像细化原图');
265%指纹图像细化过程显示如下:

266 
267 %% bwmorph组合常见形态学之骨骼化
268 clc
269 clear
270 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif');
271 subplot(131),imshow(f);
272 title('指纹图像骨骼化原图');
273 
274 fs=bwmorph(f,'skel',Inf);
275 subplot(132),imshow(fs);
276 title('指纹图像骨骼化');
277 
278 for k=1:5
279     fs=fs&~endpoints(fs);
280 end
281 subplot(133),imshow(fs);
282 title('指纹图像修剪后骨骼话');
283%指纹图像骨骼化过程显示:

284 
285 %% 使用函数bwlabel标注连通分量
286 clc
287 clear
288 f=imread('.\images\dipum_images_ch09\Fig0917(a)(ten-objects).tif');
289 imshow(f),title('标注连通分量原始图像');
290%其结果显示如下:

291 
292 [L,n]=bwlabel(f);%L为标记矩阵,n为找到连接分量的总数
293 [r,c]=find(L==3);%返回第3个对象所有像素的行索引和列索引
294 
295 rbar=mean(r);
296 cbar=mean(c);
297 
298 figure,imshow(f)
299 hold on%保持当前图像使其不被刷新
300 for k=1:n
301     [r,c]=find(L==k);
302     rbar=mean(r);
303     cbar=mean(c);
304     plot(cbar,rbar,'Marker','o','MarkerEdgeColor','k',...
305          'MarkerFaceColor','k','MarkerSize',10);%这个plot函数用法不是很熟悉
306     plot(cbar,rbar,'Marker','*','MarkerFaceColor','w');%其中的marker为标记
307 end
308 title('标记所有对象质心后的图像');

309 
310 %% 由重构做开运算
311 clc
312 clear
313 f=imread('.\images\dipum_images_ch09\Fig0922(a)(book-text).tif');
314 subplot(321),imshow(f);
315 title('重构原始图像');
316 
317 fe=imerode(f,ones(51,1));%竖线腐蚀
318 subplot(322),imshow(fe);
319 title('使用竖线腐蚀后的结果');
320 
321 fo=imopen(f,ones(51,1));%竖线做开运算
322 subplot(323),imshow(fo);
323 title('使用竖线做开运算结果');
324 
325 fobr=imreconstruct(fe,f);%fe做标记
326 subplot(324),imshow(fobr);
327 title('使用竖线做重构开运算');
328 
329 ff=imfill(f,'holes');%对f进行孔洞填充
330 subplot(325),imshow(ff);
331 title('对f填充孔洞后的图像');
332 
333 fc=imclearborder(f,8);%清除边界,2维8邻接
334 subplot(326),imshow(fc);
335 title('对f清除边界后的图像');
336%图像重构过程显示如下:

337 
338 %% 使用顶帽变换和底帽变换
339 clc
340 clear
341 f=imread('.\images\dipum_images_ch09\Fig0926(a)(rice).tif');
342 subplot(221),imshow(f);
343 title('顶帽底帽变换原始图像');
344 
345 se=strel('disk',10);%产生结构元素
346 %顶帽变换是指原始图像减去其开运算的图像
347 %而开运算可用于补偿不均匀的背景亮度,所以用一个大的结构元素做开运算后
348 %然后用原图像减去这个开运算,就得到了背景均衡的图像,这也叫做是图像的顶帽运算
349 f1=imtophat(f,se);%使用顶帽变换
350 subplot(222),imshow(f1);
351 title('使用顶帽变换后的图像');
352 
353 %底帽变换是原始图像减去其闭运算后的图像
354 f2=imbothat(imcomplement(f),se);%使用底帽变换,为什么原图像要求补呢?
355 %f2=imbothat(f,se);%使用底帽变换
356 subplot(223),imshow(f2);
357 title('使用底帽变换后的图像');
358 
359 %顶帽变换和底帽变换联合起来用,用于增加对比度
360 f3=imsubtract(imadd(f,imtophat(f,se)),imbothat(f,se));%里面参数好像不合理?
361 subplot(224),imshow(f3);
362 title('使用顶帽底帽联合变换后图像');
363%顶帽底帽变换过程图像如下:

364 
365 %%使用开运算和闭运算做形态学平滑
366 %由于开运算可以除去比结构元素更小的明亮细节,闭运算可以除去比结构元素更小的暗色细节
367 %所以它们经常组合起来一起进行平滑图像并去除噪声
368 clc
369 clear
370 f=imread('.\images\dipum_images_ch09\Fig0925(a)(dowels).tif');
371 subplot(221),imshow(f);
372 title('木钉图像原图');
373 
374 se=strel('disk',5);%disk其实就是一个八边形
375 fo=imopen(f,se);%经过开运算
376 subplot(222),imshow(f);
377 title('使用半径5的disk开运算后的图像');
378 
379 foc=imclose(fo,se);
380 subplot(223),imshow(foc);
381 title('先开后闭的图像');
382 
383 fasf=f;
384 for i=2:5
385     se=strel('disk',i);
386     fasf=imclose(imopen(fasf,se),se);
387 end
388 subplot(224),imshow(fasf);
389 title('使用开闭交替滤波后图像');
390%使用开运算和闭运算做形态学平滑结果如下:

391 
392 %% 颗粒分析
393 clc
394 clear
395 f=imread('.\images\dipum_images_ch09\Fig0925(a)(dowels).tif');
396 
397 sumpixels=zeros(1,36);
398 for k=0:35
399     se=strel('disk',k);
400     fo=imopen(f,se);
401     sumpixels(k+1)=sum(fo(:));
402 end
403 
404 %可以看到,连续开运算之间的表面积会减少
405 plot(0:35,sumpixels),xlabel('k'),ylabel('surface area');
406 title('表面积和结构元素半径之间的关系');
407%其运算结果如下:   

408 
409 figure,plot(-diff(sumpixels));%diff()函数为差分或者近似倒数,即相邻2个之间的差值
410 xlabel('k'),ylabel('surface area reduction');
411 title('减少的表面积和结构元素半径之间的关系');
412%其运算结果如下:

413 
414 %% 使用重构删除复杂图像的背景
415 clc
416 clear
417 f=imread('.\images\dipum_images_ch09\Fig0930(a)(calculator).tif');
418 subplot(221),imshow(f);
419 title('灰度级重构原图像');
420 
421 f_obr=imreconstruct(imerode(f,ones(1,71)),f);
422 subplot(222),imshow(f_obr);
423 title('经开运算重构图');
424 
425 f_o=imopen(f,ones(1,71));
426 subplot(223),imshow(f_o);
427 title('经开运算后图');
428 
429 f_thr=imsubtract(f,f_obr);
430 subplot(224),imshow(f_thr);
431 title('顶帽运算重构图')
432%使用重构删除复杂图像的背景1:

433 
434 f_th=imsubtract(f,f_o)
435 figure,subplot(221),imshow(f_th);
436 title('经顶帽运算图');
437 
438 g_obr=imreconstruct(imerode(f_thr,ones(1,11)),f_thr);
439 subplot(222),imshow(g_obr);
440 title('用水平线对f_thr经开运算后重构图');
441 
442 g_obrd=imdilate(g_obr,ones(1,2));
443 subplot(223),imshow(g_obrd);
444 title('使用水平线对上图进行膨胀');
445 
446 f2=imreconstruct(min(g_obrd,f_thr),f_thr);
447 subplot(224),imshow(f2);
448 title('最后的重构结果');
449%使用重构删除复杂图像的背景2:

 

    形态学这一章很有用,因为它还可以应用在图像分割中。

 

 

2017-01-06 14:41:33 OliverkingLi 阅读数 501
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4245 人正在学习 去看看 贾志刚

膨胀就是求局部最大值的操作(dilate),腐蚀就是求局部最小值的操作(erode),无论是膨胀操作还是腐蚀操作就是蒋图片或者额图像的一部分区域,标记为A与核标记为B进行卷积。

代码:

#include"stdafx.h"
#include <opencv2/core/utility.hpp>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include"opencv2/core/core.hpp"
#include <iostream>

using namespace cv;
using namespace std;

// 定义全局变量
Mat image, dstImage;
int g_nTrackbarNumer = 0;
int g_nStructElementSize = 3;
//函数声明
void process();
void on_TrackbarNumChange(int, void*);
void on_ElementSizeChange(int, void*);

int main() {
	system("color 5E");
	//读取图片
	image = imread("E:\\pictures\\For_Project\\New_opencv\\Sceen\\1.jpg");
	namedWindow("【原始图像】", 1);
	imshow("【原始图像】", image);

	namedWindow("【效果图】", 1);
	//创建滑动条
	createTrackbar("腐蚀/膨胀", "【效果图】", &g_nTrackbarNumer, 1, on_TrackbarNumChange);
	createTrackbar("内核尺寸", "【效果图】", &g_nStructElementSize, 21, on_ElementSizeChange);
	//分别调用回调函数
	on_TrackbarNumChange(g_nTrackbarNumer, 0);
	on_ElementSizeChange(g_nStructElementSize, 0);

	//等待键盘按键‘q’退出
	while (char(waitKey(1)) != 'q') {}
	return 0;
}

void process() {
	//自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nStructElementSize + 1, 
		2 * g_nStructElementSize + 1), Point(g_nStructElementSize, g_nStructElementSize));
	//判断进行腐蚀或者膨胀操作
	if (g_nTrackbarNumer == 0) {
		//服饰操作
		erode(image, dstImage, element);
	}
	else {
		//膨胀操作
		dilate(image, dstImage, element);
	}

	imshow("【效果图】", dstImage);
}

void on_TrackbarNumChange(int,void*) {
	process();
}

void on_ElementSizeChange(int, void *) {
	process();
}


2016-04-11 16:57:43 swj110119 阅读数 3160
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4245 人正在学习 去看看 贾志刚

前几天一直在研究形态学在图像处理中的应用,查了很多资料。首先关于图像形态学的具体理论知识,课参考如下博客:
http://www.cnblogs.com/slysky/archive/2011/10/16/2214015.html
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html

形态学操作及其公式小结:
这里写图片描述

上述操作是对二值图像进行操作的,当腐蚀、膨胀是最基本的操作,其他操作是基于这两个操作和集合论的组合。对于灰度图像来说,腐蚀和膨胀也是基本其他操作的基础,但是灰度图像腐蚀和膨胀不同于二值图像的腐蚀和膨胀。

灰度图像的腐蚀和膨胀定义如下:

(1)腐蚀:当结构元素b的原点位于(x,y)处时,用b对图像f进行腐蚀,是查找f中与结构元素b重合区域灰度级别最小的值,然后把最小的灰度值赋值给点(x,y):
这里写图片描述

(2)膨胀:当结构元素b的原点位于(x,y)处时,用b的反射(-b)对图像f进行腐蚀,是查找f中与结构元素b的反射重合区域灰度级别最大的值,然后把最大的灰度值赋值给点(x,y):
这里写图片描述

关于灰度图像的应用有:
(1)形态学梯度:
这里写图片描述

(2)顶帽变换:
这里写图片描述

(3)底帽变换:
这里写图片描述

具体代码如下:

#include<opencv.hpp>
#include<highgui.h>
#include<imgproc.hpp>
using namespace cv;

//把灰度图像转化为二值图像
Mat changeToBinaryImage(Mat grayImage)
{
    Mat binaryImage(grayImage.rows, grayImage.cols, CV_8UC1, Scalar(0));

    //转化为二值图像
    for (int i = 0; i < grayImage.rows; i++)
    {
        for (int j = 0; j < grayImage.cols; j++)
        {
            if (grayImage.data[i*grayImage.step + j]>100)
            {
                binaryImage.data[i*grayImage.step + j] = 255;
            }
            else
            {
                binaryImage.data[i*grayImage.step + j] = 0;
            }
        }
    }
    imshow("binaryImage", binaryImage);

    return binaryImage; 
}

//创建结构元素
//一般结构元素 关于原点对称
//Mat createSE()
//{
//  int a[3][3]={ 0,1,0,
//  1,1,1,
//  0,1,0};
//  Mat structureElement(3, 3, CV_8UC1, a);
//}

//二值图像腐蚀操作
Mat binaryErosion(Mat binaryImage, Mat se)
{
    //二值图像移动
    Mat window(se.rows, se.cols, CV_8UC1);

    //定义一个矩阵,存储腐蚀后的图像
    Mat binaryErosionImage(binaryImage.rows, binaryImage.cols, CV_8UC1, Scalar(0));

    for (int i = (se.rows-1)/2; i < binaryImage.rows-(se.rows-1)/2; i++)
    {
        for (int j = (se.cols - 1) / 2; j < binaryImage.cols - (se.cols - 1) / 2; j++)
        {
            //先设置第i行第j列像素值为255,即白色
            binaryErosionImage.data[i*binaryImage.step + j] = 255;
            for (int row = 0; row < se.rows; row++)
            {
                for (int col = 0; col < se.cols; col++)
                {
                    //把se对应的元素赋值到与se结构相同的矩阵中
                    window.data[row*window.step + col] = binaryImage.data[(i + row - (window.rows - 1) / 2)*binaryImage.step + (j + col - (window.cols - 1) / 2)];
                }
            }
            //比较se与window中的像素值
            int row, col;
            for (row = 0; row < se.rows; row++)
            {
                for (col = 0; col < se.cols; col++)
                {
                    if (se.data[row*se.step + col] != window.data[row*se.step + col])
                    {
                        break;
                    }
                }
                if (col == se.cols)
                {
                    continue;
                }
                else
                {
                    break;
                }
            }
            if (row == se.rows&&col == se.cols)
            {
                binaryErosionImage.data[i*binaryImage.step + j] = 0;
        }
        }
    }

    //imshow("binaryErosionImage", binaryErosionImage);

    return binaryErosionImage;
}

//二值图像膨胀操作
Mat binaryDilation(Mat binaryImage, Mat se)
{
    //二值图像移动
    Mat window(se.rows, se.cols, CV_8UC1);

    //定义一个矩阵,存储膨胀后的图像
    Mat binaryDilationImage(binaryImage.rows, binaryImage.cols, CV_8UC1, Scalar(0));

    for (int i = (se.rows - 1) / 2; i < binaryImage.rows - (se.rows - 1) / 2; i++)
    {
        for (int j = (se.cols - 1) / 2; j < binaryImage.cols - (se.cols - 1) / 2; j++)
        {
            //先设置第i行第j列像素值为255,即白色
            binaryDilationImage.data[i*binaryImage.step + j] = 255;
            for (int row = 0; row < se.rows; row++)
            {
                for (int col = 0; col < se.cols; col++)
                {
                    //把se对应的元素赋值到与se结构相同的矩阵中
                    window.data[row*window.step + col] = binaryImage.data[(i + row - (window.rows - 1) / 2)*binaryImage.step + (j + col - (window.cols - 1) / 2)];
                }
            }
            //比较se与window中的像素值
            //只要有一个相匹配 就把像素值设为0,即置黑
            int flag = 0;  //标记是否有对应相等的像素值:0表示没有,1表示有
            int row, col;
            for (row = 0; row < se.rows; row++)
            {
                for (col = 0; col < se.cols; col++)
                {
                    if (se.data[row*se.step + col] == window.data[row*se.step + col])
                    {
                        flag = 1;
                        break;
                    }
                }
                if (flag)
                {
                    break;
                }
            }
            if (flag)
            {
                //如果有交集,就设置为黑,即0
                binaryDilationImage.data[i*binaryImage.step + j] = 0;
            }
        }
    }

    //imshow("binaryDilationImage", binaryDilationImage);
    return binaryDilationImage;
}

//灰度图像腐蚀操作
Mat grayErosion(Mat grayImage,Mat se)
{
    //结构元素移动时所对应的源图像区域
    Mat window(se.rows, se.cols, CV_8UC1);

    //定义一个矩阵,存储腐蚀后的图像
    Mat grayErosionImage(grayImage.rows, grayImage.cols, CV_8UC1, Scalar(0));

    for (int i = (se.rows - 1) / 2; i < grayImage.rows - (se.rows - 1) / 2; i++)
    {
        for (int j = (se.cols - 1) / 2; j < grayImage.cols - (se.cols - 1) / 2; j++)
        {
            //先设置第i行第j列像素值为255,即白色
            grayErosionImage.data[i*grayImage.step + j] = 255;
            for (int row = 0; row < se.rows; row++)
            {
                for (int col = 0; col < se.cols; col++)
                {
                    //把se对应的元素赋值到与se结构相同的矩阵window中
                    window.data[row*window.step + col] = grayImage.data[(i + row - (window.rows - 1) / 2)*grayImage.step + (j + col - (window.cols - 1) / 2)];
                }
            }
            //比较se与window中的像素值
            //在灰度图像中,腐蚀是取window中最小的值赋值给原点所对用的像素
            int minPixel = 255;
            int row, col;
            for (row = 0; row < se.rows; row++)
            {
                for (col = 0; col < se.cols; col++)
                {
                    if (window.data[row*se.step + col] < minPixel)
                    {
                        minPixel = window.data[row*se.step + col];
                    }
                }   
            }   
            grayErosionImage.data[i*grayImage.step + j] = minPixel;
        }
    }

    /*imshow("grayErosionImage", grayErosionImage);*/

    return grayErosionImage;
}

//灰度图像膨胀操作
Mat grayDilation(Mat grayImage,Mat se)
{
    //结构元素移动时所对应的源图像区域
    Mat window(se.rows, se.cols, CV_8UC1);

    //定义一个矩阵,存储腐蚀后的图像
    Mat grayDilationImage(grayImage.rows, grayImage.cols, CV_8UC1, Scalar(0));

    for (int i = (se.rows - 1) / 2; i < grayImage.rows - (se.rows - 1) / 2; i++)
    {
        for (int j = (se.cols - 1) / 2; j < grayImage.cols - (se.cols - 1) / 2; j++)
        {
            //先设置第i行第j列像素值为255,即白色
            grayDilationImage.data[i*grayImage.step + j] = 255;
            for (int row = 0; row < se.rows; row++)
            {
                for (int col = 0; col < se.cols; col++)
                {
                    //把se对应的元素赋值到与se结构相同的矩阵window中
                    window.data[row*window.step + col] = grayImage.data[(i + row - (window.rows - 1) / 2)*grayImage.step + (j + col - (window.cols - 1) / 2)];
                }
            }
            //比较se与window中的像素值
            //在灰度图像中,膨胀是取window中最大的值赋值给原点所对用的像素
            int maxPixel = 0;
            int row, col;
            for (row = 0; row < se.rows; row++)
            {
                for (col = 0; col < se.cols; col++)
                {
                    if (window.data[row*se.step + col] > maxPixel)
                    {
                        maxPixel = window.data[row*se.step + col];
                    }
                }
            }
            grayDilationImage.data[i*grayImage.step + j] = maxPixel;
        }
    }

    /*imshow("grayDilationImage", grayDilationImage);*/

    return grayDilationImage;
}

//二值图像开操作
Mat binaryOpen(Mat binaryImage, Mat se)
{
    Mat openImage(binaryImage.rows,binaryImage.cols,CV_8UC1,Scalar(0));

    openImage = binaryDilation(binaryErosion(binaryImage, se), se);

    return openImage;
}

//二值图像闭操作
Mat binaryClose(Mat binaryImage, Mat se)
{
    Mat closeImage(binaryImage.rows, binaryImage.cols, CV_8UC1, Scalar(0));

    closeImage = binaryErosion(binaryDilation(binaryImage, se), se);

    return closeImage;
}

//灰度图像开操作
Mat grayOpen(Mat grayImage, Mat se)
{
    Mat openImage(grayImage.rows, grayImage.cols, CV_8UC1, Scalar(0));

    openImage = grayDilation(grayErosion(grayImage, se), se);

    return openImage;
}

//灰度图像闭操作
Mat grayClose(Mat grayImage, Mat se)
{
    Mat closeImage(grayImage.rows, grayImage.cols, CV_8UC1, Scalar(0));

    closeImage = grayErosion(grayDilation(grayImage, se), se);

    return closeImage;
}

//二值图像边界提取
Mat binaryBorder(Mat binaryImage,Mat se)
{
    Mat borderImage(binaryImage.rows, binaryImage.cols, CV_8UC1, Scalar(0));
    Mat erosionImage(binaryImage.rows, binaryImage.cols, CV_8UC1, Scalar(0));
    erosionImage = binaryErosion(binaryImage,se);

    for (int i = 0; i < erosionImage.rows; i++)
    {
        for (int j = 0; j < erosionImage.cols; j++)
        {
            if (binaryImage.data[i*erosionImage.step+j]!=erosionImage.data[i*erosionImage.step+j])
            {
                borderImage.data[i*erosionImage.step + j] = 255;
            }
        }
    }

    return borderImage;
}

//灰度图像边界提取
Mat grayBorder(Mat grayImage, Mat se)
{
    Mat borderImage(grayImage.rows, grayImage.cols, CV_8UC1, Scalar(0));

    borderImage = grayImage - grayErosion(grayImage, se);

    return borderImage;
}

//灰度图像梯度
Mat gradient(Mat grayImage, Mat se)
{
    Mat gradient(grayImage.rows, grayImage.cols, CV_8UC1, Scalar(0));

    gradient = grayDilation(grayImage, se) - grayErosion(grayImage, se);

    return gradient;
}

//灰度图像的顶帽运算 T(f)=f-fob
Mat topHat(Mat grayImage,Mat se)
{
    Mat topHatImage(grayImage.rows, grayImage.cols, CV_8UC1, Scalar(0));

    topHatImage = grayImage - grayOpen(grayImage,se);

    return topHatImage;
}

//灰度图像的底帽运算 B(f)=f⋅b-f
Mat bottomHat(Mat grayImage, Mat se)
{
    Mat bottomHatImage(grayImage.rows, grayImage.cols, CV_8UC1, Scalar(0));

    bottomHatImage = grayClose(grayImage, se)-grayImage;

    return bottomHatImage;
}


int main()
{
    Mat src = imread("E:\\project\\images\\32.jpg");

    Mat grayImage(src.rows, src.cols, CV_8UC1);
    //转化为灰度图像
    cvtColor(src, grayImage, CV_BGR2GRAY);

    imshow("original Image",src);
    imshow("gray Image", grayImage);

    //转化为二值图像
    Mat binaryImage = changeToBinaryImage(grayImage);

    //创建模板  一般结构元素关于自身原点对称  
    //也可以自定义结构元素  下面的变量是3*3的矩阵 全部为0  
    Mat structureElement(3, 3, CV_8UC1, Scalar(0));

    //调用二值图像腐蚀函数
    //binaryErosion(binaryImage, structureElement);
    imshow("binaryErosionImage", binaryErosion(binaryImage, structureElement));

    //调用二值图像膨胀函数
    //binaryDilation(binaryImage, structureElement);
    imshow("binaryDilationImage", binaryDilation(binaryImage, structureElement));

    //调用灰度图像腐蚀函数
    //grayErosion(grayImage, structureElement);
    imshow("grayErosionImage", grayErosion(grayImage, structureElement));

    //调用灰度图像膨胀函数
    //grayDilation(grayImage, structureElement);
    imshow("grayDilationImage", grayDilation(grayImage, structureElement));

    //调用二值图像开操作
    imshow("binaryOpenImage",binaryOpen(binaryImage,structureElement));

    //调用二值图像闭操作
    imshow("binaryCloseImage", binaryClose(binaryImage, structureElement));

    //调用灰度图像开操作
    imshow("grayOpenImage", grayOpen(grayImage, structureElement));

    //调用灰度图像闭操作
    imshow("grayCloseImage", grayClose(grayImage, structureElement));

    //二值图像边界提取
    imshow("binaryBorderImage",binaryBorder(binaryImage,structureElement));
    //灰度图像边界提取
    imshow("grayBorderImage",grayBorder(grayImage,structureElement));

    //调用灰度梯度函数
    imshow("Gradient", gradient(binaryImage, structureElement));

    //调用顶帽函数
    imshow("topHat",topHat(grayImage,structureElement));

    //调用底帽函数
    imshow("bottomHat", bottomHat(grayImage, structureElement));

    cvWaitKey(0);

    return 0;
}
2017-01-16 14:35:00 weixin_30375247 阅读数 23
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4245 人正在学习 去看看 贾志刚

【转载】:Matlab 图像处理 形态学 腐蚀 膨胀 开闭运算 连通分量

      形态学是提取图像特征的有力工具,针对二值图像和灰度图像的腐蚀、膨胀和重构的基本操作可以组合使用,以执行非常宽泛的任务。其练习代码和结果如下:

 

 
  1 %% 第9章 形态学处理
  2 
  3 %% imdilate膨胀
  4 clc
  5 clear
  6 
  7 A1=imread('.\images\dipum_images_ch09\Fig0906(a)(broken-text).tif');
  8 info=imfinfo('.\images\dipum_images_ch09\Fig0906(a)(broken-text).tif')
  9 B=[0 1 0
 10    1 1 1
 11    0 1 0];
 12 A2=imdilate(A1,B);%图像A1被结构元素B膨胀
 13 A3=imdilate(A2,B);
 14 A4=imdilate(A3,B);
 15 
 16 subplot(221),imshow(A1);
 17 title('imdilate膨胀原始图像');
 18 
 19 subplot(222),imshow(A2);
 20 title('使用B后1次膨胀后的图像');
 21 
 22 subplot(223),imshow(A3);
 23 title('使用B后2次膨胀后的图像');
 24 
 25 subplot(224),imshow(A4);
 26 title('使用B后3次膨胀后的图像');
 27%imdilate图像膨胀处理过程运行结果如下:

 28 
 29 %% imerode腐蚀
 30 clc
 31 clear
 32 A1=imread('.\images\dipum_images_ch09\Fig0908(a)(wirebond-mask).tif');
 33 subplot(221),imshow(A1);
 34 title('腐蚀原始图像');
 35 
 36 %strel函数的功能是运用各种形状和大小构造结构元素
 37 se1=strel('disk',5);%这里是创建一个半径为5的平坦型圆盘结构元素
 38 A2=imerode(A1,se1);
 39 subplot(222),imshow(A2);
 40 title('使用结构原始disk(5)腐蚀后的图像');
 41 
 42 se2=strel('disk',10);
 43 A3=imerode(A1,se2);
 44 subplot(223),imshow(A3);
 45 title('使用结构原始disk(10)腐蚀后的图像');
 46 
 47 se3=strel('disk',20);
 48 A4=imerode(A1,se3);
 49 subplot(224),imshow(A4);
 50 title('使用结构原始disk(20)腐蚀后的图像');
 51 %图像腐蚀处理过程运行结果如下:
 52 
 53 %% 开运算和闭运算
 54 clc
 55 clear
 56 f=imread('.\images\dipum_images_ch09\Fig0910(a)(shapes).tif');
 57 %se=strel('square',5');%方型结构元素 58 se=strel('disk',5');%圆盘型结构元素 59 imshow(f);%原图像
 60 title('开闭运算原始图像')
 61%运行结果如下:

 62 
 63 %开运算数学上是先腐蚀后膨胀的结果
 64 %开运算的物理结果为完全删除了不能包含结构元素的对象区域,平滑
 65 %了对象的轮廓,断开了狭窄的连接,去掉了细小的突出部分
 66 fo=imopen(f,se);%直接开运算
 67 figure,subplot(221),imshow(fo);
 68 title('直接开运算');
 69 
 70 %闭运算在数学上是先膨胀再腐蚀的结果
 71 %闭运算的物理结果也是会平滑对象的轮廓,但是与开运算不同的是,闭运算
 72 %一般会将狭窄的缺口连接起来形成细长的弯口,并填充比结构元素小的洞
 73 fc=imclose(f,se);%直接闭运算
 74 subplot(222),imshow(fc);
 75 title('直接闭运算');
 76 
 77 foc=imclose(fo,se);%先开后闭运算
 78 subplot(223),imshow(foc);
 79 title('先开后闭运算');
 80 
 81 fco=imopen(fc,se);%先闭后开运算
 82 subplot(224),imshow(fco);
 83 title('先闭后开运算');
 84%开闭运算结果如下:

 85 
 86 %先膨胀再腐蚀
 87 fse=imdilate(f,se);%膨胀
 88 
 89 %gcf为得到当前图像的句柄,当前图像是指例如PLOT,TITLE,SURF等
 90 %get函数为得到物体的属性,get(0,'screensize')为返回所有物体screensize属性值
 91 %set函数为设置物体的属性
 92 figure,set(gcf,'outerposition',get(0,'screensize'));%具体目的是设置当前窗口的大小
 93 subplot(211),imshow(fse);
 94 title('使用disk(5)先膨胀后的图像');
 95 
 96 fes=imerode(fse,se);
 97 subplot(212),imshow(fes);
 98 title('使用disk(5)先膨胀再腐蚀后的图像');
 99%先膨胀后腐蚀图像如下:

100 
101 %先腐蚀再膨胀
102 fse=imerode(f,se);
103 figure,set(gcf,'outerposition',get(0,'screensize'))
104 subplot(211),imshow(fse);
105 title('使用disk(5)先腐蚀后的图像');
106 
107 fes=imdilate(fse,se);
108 subplot(212),imshow(fes);
109 title('使用disk(5)先腐蚀再膨胀后的图像');
110%先腐蚀后膨胀的图像如下:

111 
112 %% imopen imclose在指纹上的应用
113 clc
114 clear
115 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif');
116 se=strel('square',3);%边长为3的方形结构元素
117 subplot(121),imshow(f);
118 title('指纹原始图像');
119 
120 A=imerode(f,se);%腐蚀
121 subplot(122),imshow(A);
122 title('腐蚀后的指纹原始图像');
123%指纹原始图像和腐蚀后的图像结果如下:

124 
125 fo=imopen(f,se);
126 figure,subplot(221),imshow(fo);
127 title('使用square(3)开操作后的图像');
128 
129 fc=imclose(f,se);
130 subplot(222),imshow(fc);
131 title('使用square闭操作后的图像');
132 
133 foc=imclose(fo,se);
134 subplot(223),imshow(foc);
135 title('使用square(3)先开后闭操作后的图像')
136 
137 fco=imopen(fc,se);
138 subplot(224),imshow(fco);
139 title('使用square(3)先闭后开操作后的图像');
140%指纹图像开闭操作过程结果如下:

141 
142 %% bwhitmiss击中或击不中变换
143 clc
144 clear
145 f=imread('.\images\dipum_images_ch09\Fig0913(a)(small-squares).tif');
146 imshow(f);
147 title('击中或不击中原始图像');
148%击中或不击中原始图像显示结果如下:

149 
150 B1=strel([0 0 0;0 1 1;0 1 0]);%击中:要求击中所有1的位置
151 B2=strel([1 1 1;1 0 0;1 0 0]);%击不中,要求击不中所有1的位置
152 B3=strel([0 1 0;1 1 1;0 1 0]);%击中
153 B4=strel([1 0 1;0 0 0;0 0 0]);%击不中
154 B5=strel([0 0 0;0 1 0;0 0 0]);%击中
155 B6=strel([1 1 1;1 0 0;1 0 0]);%击不中
156 
157 g=imerode(f,B1)&imerode(~f,B2)%利用定义来实现击中或击不中
158 figure,subplot(221),imshow(g);
159 title('定义实现组1击中击不中图像');
160 
161 g1=bwhitmiss(f,B1,B2);
162 subplot(222),imshow(g1);
163 title('结构数组1击中击不中后的图像');
164 
165 g2=bwhitmiss(f,B3,B4);
166 subplot(223),imshow(g2);
167 title('结构数组2击中击不中的图像');
168 
169 g3=bwhitmiss(f,B5,B6);
170 subplot(224),imshow(g3);
171 title('结构数组3击中击不中的图像');
172%击中击不中变换后图像如下:

173 
174 %%makelut
175 clc
176 clear
177 
178 f=inline('sum(x(:))>=3');%inline是用来定义局部函数的
179 lut2=makelut(f,2)%为函数f构造一个接收2*2矩阵的查找表
180 lut3=makelut(f,3)
181 
182 %% Conway生命游戏
183 clc
184 clear
185 lut=makelut(@conwaylaws,3);
186 bw1=  [0     0     0     0     0     0     0     0     0     0
187        0     0     0     0     0     0     0     0     0     0
188        0     0     0     1     0     0     1     0     0     0
189        0     0     0     1     1     1     1     0     0     0
190        0     0     1     0     0     0     0     1     0     0
191        0     0     1     0     1     1     0     1     0     0
192        0     0     1     0     0     0     0     1     0     0
193        0     0     0     1     1     1     1     0     0     0
194        0     0     0     0     0     0     0     0     0     0
195        0     0     0     0     0     0     0     0     0     0  ];
196 subplot(221),imshow(bw1,'InitialMagnification','fit');
197 title('Generation 1');
198 
199 bw2=applylut(bw1,lut);
200 subplot(222),imshow(bw2,'InitialMagnification','fit'),
201 title('Generation 2');
202 
203 bw3=applylut(bw2,lut);
204 subplot(223),imshow(bw3,'InitialMagnification','fit');
205 title('Generation 3');
206 
207 temp=bw1;
208 for i=2:100
209     bw100=applylut(temp,lut);
210     temp=bw100;
211 end
212 subplot(224),imshow(bw100,'InitialMagnification','fit')
213 title('Generation 100');
214%显示Generation结果如下:

215 
216 %% getsequence
217 clc
218 clear
219 se=strel('diamond',5)
220 decomp=getsequence(se)%getsequence函数为得到分解的strel序列
221 decomp(1)
222 decomp(2)
223 
224 %% endpoints
225 clc
226 clear
227 
228 f1=imread('.\images\dipum_images_ch09\Fig0914(a)(bone-skel).tif');
229 subplot(121),imshow(f1);
230 title('原始形态骨架图像');
231 
232 g1=endpoints(f1);
233 %set(gcf,'outerposition',get(0,'screensize'));%运行完后自动生成最大的窗口
234 subplot(122),imshow(g1);
235 title('骨架图像的端点图像');
236 %骨架头像端点检测头像如下:
237 
238 f2=imread('.\images\dipum_images_ch09\Fig0916(a)(bone).tif');
239 figure,subplot(121),imshow(f2);
240 title('原始骨头图像');
241 
242 g2=endpoints(f2);
243 subplot(122),imshow(g2);
244 title('骨头图像端点头像');%结果是没有端点
245%骨头头像端点检测图像如下:

246 
247 %% bwmorph组合常见形态学之细化
248 clc
249 clear
250 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif');
251 subplot(221),imshow(f);
252 title('指纹图像细化原图');
253 
254 g1=bwmorph(f,'thin',1);
255 subplot(222),imshow(g1);
256 title('指纹图像细化原图');
257 
258 g2=bwmorph(f,'thin',2);
259 subplot(223),imshow(g2);
260 title('指纹图像细化原图');
261 
262 g3=bwmorph(f,'thin',Inf);
263 subplot(224),imshow(g3);
264 title('指纹图像细化原图');
265%指纹图像细化过程显示如下:

266 
267 %% bwmorph组合常见形态学之骨骼化
268 clc
269 clear
270 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif');
271 subplot(131),imshow(f);
272 title('指纹图像骨骼化原图');
273 
274 fs=bwmorph(f,'skel',Inf);
275 subplot(132),imshow(fs);
276 title('指纹图像骨骼化');
277 
278 for k=1:5
279     fs=fs&~endpoints(fs);
280 end
281 subplot(133),imshow(fs);
282 title('指纹图像修剪后骨骼话');
283%指纹图像骨骼化过程显示:

284 
285 %% 使用函数bwlabel标注连通分量
286 clc
287 clear
288 f=imread('.\images\dipum_images_ch09\Fig0917(a)(ten-objects).tif');
289 imshow(f),title('标注连通分量原始图像');
290%其结果显示如下:

291 
292 [L,n]=bwlabel(f);%L为标记矩阵,n为找到连接分量的总数
293 [r,c]=find(L==3);%返回第3个对象所有像素的行索引和列索引
294 
295 rbar=mean(r);
296 cbar=mean(c);
297 
298 figure,imshow(f)
299 hold on%保持当前图像使其不被刷新
300 for k=1:n
301     [r,c]=find(L==k);
302     rbar=mean(r);
303     cbar=mean(c);
304     plot(cbar,rbar,'Marker','o','MarkerEdgeColor','k',...
305          'MarkerFaceColor','k','MarkerSize',10);%这个plot函数用法不是很熟悉
306     plot(cbar,rbar,'Marker','*','MarkerFaceColor','w');%其中的marker为标记
307 end
308 title('标记所有对象质心后的图像');

309 
310 %% 由重构做开运算
311 clc
312 clear
313 f=imread('.\images\dipum_images_ch09\Fig0922(a)(book-text).tif');
314 subplot(321),imshow(f);
315 title('重构原始图像');
316 
317 fe=imerode(f,ones(51,1));%竖线腐蚀
318 subplot(322),imshow(fe);
319 title('使用竖线腐蚀后的结果');
320 
321 fo=imopen(f,ones(51,1));%竖线做开运算
322 subplot(323),imshow(fo);
323 title('使用竖线做开运算结果');
324 
325 fobr=imreconstruct(fe,f);%fe做标记
326 subplot(324),imshow(fobr);
327 title('使用竖线做重构开运算');
328 
329 ff=imfill(f,'holes');%对f进行孔洞填充
330 subplot(325),imshow(ff);
331 title('对f填充孔洞后的图像');
332 
333 fc=imclearborder(f,8);%清除边界,2维8邻接
334 subplot(326),imshow(fc);
335 title('对f清除边界后的图像');
336%图像重构过程显示如下:

337 
338 %% 使用顶帽变换和底帽变换
339 clc
340 clear
341 f=imread('.\images\dipum_images_ch09\Fig0926(a)(rice).tif');
342 subplot(221),imshow(f);
343 title('顶帽底帽变换原始图像');
344 
345 se=strel('disk',10);%产生结构元素
346 %顶帽变换是指原始图像减去其开运算的图像
347 %而开运算可用于补偿不均匀的背景亮度,所以用一个大的结构元素做开运算后
348 %然后用原图像减去这个开运算,就得到了背景均衡的图像,这也叫做是图像的顶帽运算
349 f1=imtophat(f,se);%使用顶帽变换
350 subplot(222),imshow(f1);
351 title('使用顶帽变换后的图像');
352 
353 %底帽变换是原始图像减去其闭运算后的图像
354 f2=imbothat(imcomplement(f),se);%使用底帽变换,为什么原图像要求补呢?
355 %f2=imbothat(f,se);%使用底帽变换
356 subplot(223),imshow(f2);
357 title('使用底帽变换后的图像');
358 
359 %顶帽变换和底帽变换联合起来用,用于增加对比度
360 f3=imsubtract(imadd(f,imtophat(f,se)),imbothat(f,se));%里面参数好像不合理?
361 subplot(224),imshow(f3);
362 title('使用顶帽底帽联合变换后图像');
363%顶帽底帽变换过程图像如下:

364 
365 %%使用开运算和闭运算做形态学平滑
366 %由于开运算可以除去比结构元素更小的明亮细节,闭运算可以除去比结构元素更小的暗色细节
367 %所以它们经常组合起来一起进行平滑图像并去除噪声
368 clc
369 clear
370 f=imread('.\images\dipum_images_ch09\Fig0925(a)(dowels).tif');
371 subplot(221),imshow(f);
372 title('木钉图像原图');
373 
374 se=strel('disk',5);%disk其实就是一个八边形
375 fo=imopen(f,se);%经过开运算
376 subplot(222),imshow(f);
377 title('使用半径5的disk开运算后的图像');
378 
379 foc=imclose(fo,se);
380 subplot(223),imshow(foc);
381 title('先开后闭的图像');
382 
383 fasf=f;
384 for i=2:5
385     se=strel('disk',i);
386     fasf=imclose(imopen(fasf,se),se);
387 end
388 subplot(224),imshow(fasf);
389 title('使用开闭交替滤波后图像');
390%使用开运算和闭运算做形态学平滑结果如下:

391 
392 %% 颗粒分析
393 clc
394 clear
395 f=imread('.\images\dipum_images_ch09\Fig0925(a)(dowels).tif');
396 
397 sumpixels=zeros(1,36);
398 for k=0:35
399     se=strel('disk',k);
400     fo=imopen(f,se);
401     sumpixels(k+1)=sum(fo(:));
402 end
403 
404 %可以看到,连续开运算之间的表面积会减少
405 plot(0:35,sumpixels),xlabel('k'),ylabel('surface area');
406 title('表面积和结构元素半径之间的关系');
407%其运算结果如下:   

408 
409 figure,plot(-diff(sumpixels));%diff()函数为差分或者近似倒数,即相邻2个之间的差值
410 xlabel('k'),ylabel('surface area reduction');
411 title('减少的表面积和结构元素半径之间的关系');
412%其运算结果如下:

413 
414 %% 使用重构删除复杂图像的背景
415 clc
416 clear
417 f=imread('.\images\dipum_images_ch09\Fig0930(a)(calculator).tif');
418 subplot(221),imshow(f);
419 title('灰度级重构原图像');
420 
421 f_obr=imreconstruct(imerode(f,ones(1,71)),f);
422 subplot(222),imshow(f_obr);
423 title('经开运算重构图');
424 
425 f_o=imopen(f,ones(1,71));
426 subplot(223),imshow(f_o);
427 title('经开运算后图');
428 
429 f_thr=imsubtract(f,f_obr);
430 subplot(224),imshow(f_thr);
431 title('顶帽运算重构图')
432%使用重构删除复杂图像的背景1:

433 
434 f_th=imsubtract(f,f_o)
435 figure,subplot(221),imshow(f_th);
436 title('经顶帽运算图');
437 
438 g_obr=imreconstruct(imerode(f_thr,ones(1,11)),f_thr);
439 subplot(222),imshow(g_obr);
440 title('用水平线对f_thr经开运算后重构图');
441 
442 g_obrd=imdilate(g_obr,ones(1,2));
443 subplot(223),imshow(g_obrd);
444 title('使用水平线对上图进行膨胀');
445 
446 f2=imreconstruct(min(g_obrd,f_thr),f_thr);
447 subplot(224),imshow(f2);
448 title('最后的重构结果');
449%使用重构删除复杂图像的背景2:

 

 

    形态学这一章很有用,因为它还可以应用在图像分割中。

 


 

转载于:https://www.cnblogs.com/daxiongblog/p/6289551.html

2014-12-25 19:47:53 TonyShengTan 阅读数 9918
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4245 人正在学习 去看看 贾志刚

学习DIP第12天

转载请标明出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不满意。。。。。。。。

开篇废话

    今天来介绍形态学中最基础也是最重要的两个操作,腐蚀和膨胀,腐蚀和膨胀基本上是所有形态学操作的基础,除此之外还有补集(即二值图全部取反的操作,0变1,1变0),和反射(将所有坐标去反)。

    之前使用过腐蚀和膨胀,仅仅是去噪,那时候连结构元(SE)的概念都没有,其实所有形态学操作,核心都是结构元(包括其形状和中心位置,中心位置可以不在结构元区域中),他的变化可以产生千奇百怪的效果,如果你能很好的设计结构元,那么你将能得到你想要的效果。

    对于写博客,我觉得坚持下来还是不错的,一是可以反思总结一下学习结果,很多收获都是写博客的时候想到的,虽然写起来浪费很多时间,包括作图之类的工作。二是可以作为资料,以后查看,查漏补缺。三是与别人分享知识,如果有问题,可以有人及时指正,良师益友。

 

应用

 内容迁移至 

http://www.face2ai.com/DIP-3-2-二值图像-形态学处理2-腐蚀和膨胀/

 

 http://www.tony4ai.com/DIP-3-2-二值图像-形态学处理2-腐蚀和膨胀/

没有更多推荐了,返回首页