中国史之【昭王攻荆楚】:
周天子周昭王三次南征楚国的战争。周昭王亲率六师南征楚国,在汉水边准备渡江时,因为船只被人做了手脚而沉入水中,周人丧失六师于汉水中,遭到全军覆没的惨败。
——来源:全历史APP
【路漫漫其修远兮,吾将上下而求索】
今天介绍图像的逻辑运算实践。单看课本知识,不去动手,难以体会到视觉效果的冲击感。本内容参考自《实用MATLAB图像和视频处理》第6章。
图像处理工具包中提供了4个函数用于进行图像逻辑运算,分别是bitand、bitor、bitcmp、bitxor,还包括roipoly函数来生成图像掩膜。
逻辑操作符常用于图像掩膜,通过使用roipoly函数来生成图像掩膜。一旦有了掩膜,便可以使用它对选择的图像进行逻辑运算。下面使用函数roipoly来生成一幅图像的掩膜。
%使用函数roipoly来生成一幅图像的掩膜
I = imread('pout.tif');
bw = roipoly(I);
figure
subplot(1,2,1), imshow(I), title('pout');
subplot(1,2,2), imshow(bw), title('Mask pout');
这里要注意roiploy的用法,我摸索了好久才明白。它会交互式地打开窗口,然后我们使用鼠标来标记我们需要的掩膜,必须刚好终点回到原点,围成一圈后才能生成想要的掩膜。如下图所示。
如上,我们还没形成闭环前,是不会生成掩膜。当形成闭环后,如果还是没有生成掩膜,我们可以在交接点处鼠标点多几下,直到出现下图的工作区出现logical类型的数据,表示掩膜已生成。
我们可以观察到掩膜和原图是同样的大小,这是进行逻辑运算的前提,必须保证和原图有相同的比特数,同样的尺寸。可视化掩码的效果如下:
这一步,简称手动抠图。下一步,我们将其转换成uint8类型,即每个像素用uint8比特比较,这样才能进行逻辑运算。
bw2 = uint8(bw);
I2 = bitand(I, bw2);
figure
subplot(1,3,1), imshow(I), title('pout');
subplot(1,3,2), imshow(bw), title('Mask pout');
subplot(1,3,3), imshow(I2), title('Bitand pout');
最终运行逻辑与的效果如下,变成全黑了:
为什么会这样?我们深究一下里面的像素。通过查看工作区上面的文件,发现通过uint(8)转换后的bw2是一系列0和1的像素,其最大值是1。通过与运算后,最终的I2图像也全是0和1像素,所以看上去就是全黑。
既然这样,我们可以尝试使用im2uint(8)来转换bw图像,看看效果。
%使用函数bitand来计算一幅图像的逻辑与
I = imread('pout.tif');
bw =roipoly(I);
%bw2 = uint8(bw);
bw2 = im2uint8(bw);
I2 = bitand(I, bw2);
figure
subplot(1,3,1), imshow(I), title('pout');
subplot(1,3,2), imshow(bw), title('Mask pout');
subplot(1,3,3), imshow(I2), title('Bitand pout');
从上面第三个图片可以看出,使用im2uint8函数转换的图片,其像素值是0和255,这样通过与运算便可得到相应的抠图。bw2的像素值如下:
bitcmp是图像的非运算,其实是比特求补,也就是0变1,1变0。我们回到只有0和1像素的掩膜bw2,对其进行求补。代码和效果如下:
%使用函数bitcmp来计算一幅图像的逻辑非
I = imread('pout.tif');
bw =roipoly(I);
bw2 = uint8(bw);
bw_cmp = bitcmp(bw2);
figure
subplot(1,3,1), imshow(I), title('pout');
subplot(1,3,2), imshow(bw2), title('Mask pout');
subplot(1,3,3), imshow(bw_cmp), title('Not Mask pout');
我们可以看到bw2求补后变成全白,因为它的像素值是全255。
我们现在可以将原图和求补后的图掩膜计算逻辑或。代码如下:
%使用函数bitor来计算一幅图像的逻辑或
I = imread('pout.tif');
bw =roipoly(I);
bw2 = uint8(bw); % 原始掩膜
bw_cmp = bitcmp(bw2); % 求补掩膜
I2 = bitor(I, bw_cmp); % 原图和补掩膜求逻辑或
I3 = bitor(I, bw2); % 原图和原掩膜求逻辑或
figure
subplot(1,3,1), imshow(I), title('pout');
subplot(1,3,2), imshow(I2), title('Mask with bitcmp pout');
subplot(1,3,3), imshow(I3), title('Mask with pout');
从上面可以看到,原图和补掩膜求逻辑或,是一片全白。因为补掩膜本来就是全白,或操作是有1即1。而对原掩膜进行逻辑或,最终生成原图。因为原掩膜是0和1像素,对于逻辑或操作,全0才0。
终于快写完了。异或操作也很常用,最常用于检查两幅图像是否完全一致。因为异或运算是不同为1,相同为0。所以,XOR操作常用于寻找两幅图像之间的差别。
这个应该很好理解。其代码和效果如下:
%使用函数bitxor来计算一幅图像的异或操作
I = imread('cameraman.tif');
I2 = imread('cameraman2.tif');
I_xor = bitxor(I, I2);
figure
subplot(1,3,1), imshow(I), title('Image 1');
subplot(1,3,2), imshow(I2), title('Image 2');
subplot(1,3,3), imshow(I_xor), title('XOR Image');
如果没有认真看,还真看不出来,中间的图片相对于左边的图片,在正右边多了一块建筑。通过异或操作就可简单地找出来。注意,这种异或是按比特进行比较的。
我们使用imdivide来调暗图片,然后构造多边形感兴趣区域来生成掩膜,利用逻辑操作来实现在感兴趣区域显示调暗的图像,而其他地方显示原图。代码和效果如下:
%使用算术和逻辑函数来实现一幅图像在感兴趣区域显示调暗的图像,而其他地方显示原图
I = imread('lindsay.tif');
I_adj = imdivide(I, 1.5);
bw = im2uint8(roipoly(I));
bw_cmp = bitcmp(bw); %掩膜求补
roi = bitor(I_adj, bw_cmp); %感兴趣区域
not_roi = bitor(I, bw); %非感兴趣区域
new_img = bitand(roi, not_roi); %生成新图像
figure
subplot(1,2,1), imshow(I), title('Image');
subplot(1,2,2), imshow(new_img), title('new Image');
图像加法——imadd
图像减法——imsubtract
图像乘法——immultiply
图像除法——imdivide
AND运算——bitand
OR运算——bitor
NOT运算——bitcmp
XOR运算——bitxor
以上是本期内容,建议自己动手来实践一下。如果需要图片和代码,可以关注公众号,回复关键字【matlab代码】即可获得。我会上传到云盘。
【声明】:学习笔记基于互联网上各种学习资源的个人整理。
以上是本期内容,下期介绍图像处理的几何操作。
我叫小保,一名计算机视觉爱好者、学习者、追随者,欢迎关注我【CV之道】一起学习。