实验一 数学形态学图像处理
实验内容与要求
- 使用结构元素函数strel分别定义'square'和'disk'形状的结构元素,对下图(a)所示的二值图像进行腐蚀(imerode)和膨胀(imdilate)操作,分析腐蚀和膨胀运算的作用。
- 结合腐蚀和膨胀运算,使用开运算(imopen)和闭运算(imclose),对下图(b)所示的二值图像进行开运算和闭运算处理,分析开运算和闭运算的作用。
- 利用数学形态学函数bwmorph(BW,'skel',Inf),对下图(c)和(d)所示二值图像的目标提取骨架,并分析骨架结构。其中,BW表示二值图像。
- 利用数学形态学函数imfill(BW,'holes')对于上图(e)和(f)所示二值图像中的孔洞进行填充。其中,BW表示二值图像。
- 读取米粒图像(rice.png),利用形态学算法计算图中目标的数量,写出详细的处理步骤。
第一问
想对图形进行腐蚀或是膨胀的操作,需要有结构元素,MATLAB中strel函数的作用就是如此。 其中腐蚀操作会将图像中与结构元素的映射平移含于图像的原点位置像素去除。而膨胀操作会将图像中与结构元素映射平移存在交点的原点位置像素加入图像中。 综上,腐蚀操作会将图像中目标边界的像素移除,而膨胀操作会扩充目标边界的像素。 所以问题的答案是——腐蚀会将图中白色区域的边界像素移除,随着结构元素规格增大,效果会更加明显,同时还可能会使三个圆相连接的部分出现断开的情况 膨胀则会将图像的边界扩张,随着结构元素的规格增大,效果会更加明显,但同时会出现图形边界出现凸起的现象。
第二问
开运算是先腐蚀后膨胀,闭运算是先膨胀后腐蚀。其中开运算会将结构元素在目标区域边界内进行平移。闭运算则会将结构元素在目标区域边界外进行平移。 开运算会将图形中细小的突出部分消除,并且会将细小的桥接部分断开,随着结构元素的规格变大,此效果会愈发明显,所以开运算会将图b中的三角变为圆角,并且如果结构元素过大,会将中间的圆形与外部白色区域断开,形成三个不完全的独立的小三角。 闭运算会将目标区域中的小尺寸孔洞和缺口填补,桥接狭窄断裂部分。
第三问
老师上课没讲,等等看个博客。
第四问
直接调用API即可
第五问
首先看需求,要数图中米粒数量,很容易想到一个方法,做依据threshold的影像二值化,把米粒变成1,背景变成0。
MATLAB中可以根据graythresh
函数来找到一幅图的最佳阈值,然后根据此阈值使用im2bw方法对图片进行二值化
但图片效果并不理想,在图片下半部分的米粒无法被正常标出,这是因为图片的背景并不均匀,在中间部分的米粒背景较亮,而下半部分的米粒背景又较暗。并且图中存在有些许的sparkle,即白色的斑点,这是因为较亮处背景中有些pixel被误认作了米粒。
要解决这个问题,我们可以采用另外的方式识别米粒,例如先识别出图片背景,让原图减去图片背景,得到的就是目标前景。
如何得到图片背景呢,可以对图片进行开运算。开运算得到图片背景后,利用imsubtract
函数做减法,得到米粒部分。
值得注意的是,在得到做减法的图片后,发现图片相较于原来变得更暗了,这是因为每张图片减去其他一张图片后,肯定会得到灰度值更小的图片。
在最终对米粒进行计数前,还有一个小问题,那就是图片中存在很多的blob,也可以叫做connected component,也就是图片中在边缘部分的米粒,并不是完整的,要想个办法解决
采用的方法叫做labeling matrix
,其原理很简单,我们遍历图片的每个pixel,如果当前pixel是1,那么就从当前像素进行DFS,在DFS过程中,对处理完毕的pixel置为0,避免重复处理(类似于visited数组),同时维护一个全局的label变量,第一颗米粒对应的label就是1,第二颗就是2,以此类推……每当在DFS过程中遇到相邻的值为1的像素时,就对其在label matrix(标签矩阵)中的值置为当前的label变量,这样当我们遍历完全图后,就得到了label个米粒。在MATLAB中,任何计算都以column为单位,所以最终得到的矩阵是以列从上到下排序的。
想要得到米粒的平均area或是最大area也很简单,我们可以使用built-in function find()
来查找,同样也可以遍历整幅图,维护一个数组或是map,记录每个label对应米粒的pixel数量,选取最大的一个label就可以了。
最终为图中的米粒打上标签后,我们还可以使用label2rgb()
函数将图中的米粒置为彩色,其中色调越冷代表越小,色调越暖代表越大。
除此之外,值得一提的是,如果想将图中的所有米粒都变为红色,背景采用黑色,该如何解决呢?我们可以将图片转为color-image,对其中第一层的grain置255,剩下两层的grain置0,这样grain的值就为(255,0,0),也就是红色了。
另外还有一个函数regionprops
,这个函数需要传入二值化图像和你想要得到的properties,以传入properties为"basic"为例,会返回三个变量,分别为area
、centroid
、boundingbox
,其中area代表每个图中米粒区域的实际像素数,也就是面积,而centroid则返回每个米粒的中心位置的坐标,那么显而易见的,通过area和centroid,我们可以得出米粒左上角和右下角的坐标,这样就可以拉出一个box(多边形)将米粒包围。
实验二 图像分割
实验内容与要求
- 分别用Roberts、Prewitt、Sobel(BW1 = edge(I,'sobel'))、Canny(BW2 = edge(I,'canny'))和LOG算子对coins.png灰度图像进行边缘检测,比较这几种算子的处理结果,并总结它们各自的优劣。
- 对rice.png图像使用双峰法进行图像分割。实现方法:读取图像,显示其灰度直方图,观察直方图,选择两个波峰之间的波谷对应的灰度值作为最优阈值,通过im2bw()函数进行图像分割。
- 对coins.png等多幅灰度图像采用Otsu算法(graythresh函数获取图像分割的最优阈值)进行图像分割,显示分割结果,并分析该方法的优劣。