OpenCV-python数学形态学
实验一
实验内容
通过图像膨胀和腐蚀操作获取图像的边缘
代码注释
import cv2
import numpy as np# 实验1
# 读取输入图像,转换为灰度图像
image = cv2.imread("../test2.jpg", 0)# 构造一个3×3的结构元素
element = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))# 对图像进行膨胀操作
dilate = cv2.dilate(image, element)# 对图像进行腐蚀操作
erode = cv2.erode(image, element)# 将膨胀后的图像和腐蚀后的图像相减,得到边缘图像
result = cv2.absdiff(dilate, erode)# 上面得到的结果是灰度图,将其二值化以便更清楚地观察结果
# 使用阈值化函数将灰度值大于40的像素设置为255,其他像素设置为0
retval, result = cv2.threshold(result, 40, 255, cv2.THRESH_BINARY)# 对二值图进行反色操作,即将白色像素变为黑色,黑色像素变为白色
result = cv2.bitwise_not(result)# 显示图像
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
功能说明
首先,使用cv2.imread()
函数读取输入图像test2.jpg
并转换为灰度图像。
接下来,通过cv2.getStructuringElement()
函数构造一个3x3的矩形结构元素,用于膨胀和腐蚀操作。
然后,分别对输入图像进行膨胀和腐蚀操作,得到膨胀图像dilate
和腐蚀图像erode
。
接着,通过cv2.absdiff()
函数将膨胀图像和腐蚀图像进行相减操作,获得边缘图像result
。
为了更清晰地观察结果,将result
进行二值化处理,使用cv2.threshold()
函数将阈值设置为40,将灰度值大于40的像素设置为255,其他像素设置为0。
接下来,通过cv2.bitwise_not()
函数对二值图进行反色操作,将每个像素取反。
最后,通过cv2.imshow()
函数显示结果图像并等待用户按下任意键,最后通过cv2.destroyAllWindows()
函数关闭窗口。
效果展示
效果比较分析
效果只展示了获取边缘后的图像以及我们能查看的原图,通过对比实验结果和原始图像,可以观察到边缘图像中物体的边缘轮廓更加明显。
结论
通过图像膨胀、腐蚀、二值化和反色等操作,可以提取出图像中的边缘信息,并对边缘进行处理以得到更清晰的边界线。
实验二
实验内容
这段代码实现了一个图像的 Hit or Miss 变换。它首先创建了一个输入图像和一个核。然后,通过调用 cv.morphologyEx()
函数使用 MORPH_HITMISS 参数进行变换,将输入图像和核进行匹配。
代码注释
import cv2 as cv
import numpy as np# 创建输入图像
input_image = np.array(([0, 0, 0, 0, 0, 0, 0, 0],[0, 255, 255, 255, 0, 0, 0, 255],[0, 255, 255, 255, 0, 0, 0, 0],[0, 255, 255, 255, 0, 255, 0, 0],[0, 0, 255, 0, 0, 0, 0, 0],[0, 0, 255, 0, 0, 255, 255, 0],[0, 255, 0, 255, 0, 0, 255, 0],[0, 255, 255, 255, 0, 0, 0, 0]), dtype="uint8")# 创建核
kernel = np.array(([0, 1, 0],[1, -1, 1],[0, 1, 0]), dtype="int")# 创建输出图像,并进行变换
output_image = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel)# 为便于观察,将输入图像、输出图像、核放大五十倍,显示,一个小方块表示一个像素
rate = 50
kernel = (kernel + 1) * 127
kernel = np.uint8(kernel)
kernel = cv.resize(kernel, None, fx=rate, fy=rate, interpolation=cv.INTER_NEAREST)
cv.imshow("kernel", kernel)
cv.moveWindow("kernel", 0, 0)
input_image = cv.resize(input_image, None, fx=rate, fy=rate, interpolation=cv.INTER_NEAREST)
cv.imshow("Original", input_image)
cv.moveWindow("Original", 0, 200)
output_image = cv.resize(output_image, None, fx=rate, fy=rate, interpolation=cv.INTER_NEAREST)
cv.imshow("Hit or Miss", output_image)
cv.moveWindow("Hit or Miss", 500, 200)
cv.waitKey(0)
cv.destroyAllWindows()
功能说明
这段代码的功能是进行 Hit or Miss 变换,完成以下操作:
- 定义一个输入图像
input_image
,用来表示图像中的像素值(0为背景,255为前景)。 - 定义一个核
kernel
,用来匹配输入图像中的某个特定模式。 - 使用
cv.morphologyEx()
函数,将输入图像和核进行 Hit or Miss 变换,得到输出图像output_image
。 - 为了方便观察,将输入图像、输出图像和核分别放大 50 倍,并在窗口中显示,每个小方块表示一个像素。
- 最后,通过调用
cv.waitKey(0)
等待用户按下任意键以关闭图像窗口,再调用cv.destroyAllWindows()
关闭所有窗口。
通过这段代码,可以观察到 Hit or Miss 变换操作后得到的输出图像,以及核在输入图像上滑动以匹配特定模式的过程。这种变换常用于图像处理任务中的模式匹配和形状检测。
效果展示
Original
kernel
Hit or Miss
效果比较分析
通过对比原始图像、输出图像和核,可以观察到不同的视觉效果。原始图像是一个灰度图像,其中前景像素(255)表示物体的轮廓。输出图像则是经过 Hit or Miss 变换后得到的结果,提取出了输入图像中匹配核模式的边缘信息。
结论
通过 Hit or Miss 变换,可以提取出输入图像中匹配核模式的边缘信息,并通过显示图像进行观察和分析。这种边缘检测的方法可以应用于形状检测、目标识别等图像处理任务中。
实验三
实验内容
这段代码实现了对输入图像进行形态学操作,提取出水平线或垂直线的效果。首先,读取输入图像并将其转换为灰度图像。然后,通过自适应阈值处理将灰度图像转换为二值图像。接下来,使用形态学操作提取出水平线或垂直线。最后,将提取出的线条图像进行显示。
代码注释
import cv2src = cv2.imread("test3.jpg")
gray_src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
cv2.imshow("input image", src)
cv2.imshow("gray image", gray_src)
gray_src = cv2.bitwise_not(gray_src)
binary_src = cv2.adaptiveThreshold(gray_src, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 15, -2)
cv2.namedWindow("result image", cv2.WINDOW_AUTOSIZE)
cv2.imshow("result image", binary_src)提取水平线
hline = cv2.getStructuringElement(cv2.MORPH_RECT, ((src.shape[1] // 16), 1), (-1, -1))提取垂直线
vline = cv2.getStructuringElement(cv2.MORPH_RECT, (1, (src.shape[0] // 16)), (-1, -1))这两步就是形态学的开操作——先腐蚀再膨胀
temp = cv2.erode(binary_src, hline)
dst = cv2.dilate(temp, hline)
dst = cv2.morphologyEx(binary_src, cv2.MORPH_OPEN, vline) # vline改成hline可以看到水平线
dst = cv2.bitwise_not(dst)
cv2.imshow("vline image", dst)
cv2.waitKey(0)
功能说明
这段代码的功能是对输入图像进行处理,提取出图像中的垂直线(或水平线)。
具体操作如下:
- 读取图像并显示输入图像和灰度图像。
- 对灰度图像进行取反,将背景变成前景。
- 进行自适应阈值分割,将灰度图像转换为二值图像,并显示处理结果。
- 定义提取水平线的核
hline
和提取垂直线的核vline
。 - 使用腐蚀与膨胀操作进行形态学的开操作,提取出垂直线(或水平线)。
- 将提取的线条图像取反,得到最终的处理结果,并在窗口中显示。
- 通过等待键盘输入来保持图像窗口的显示状态。
通过这段代码,可以观察到图像中的垂直线(或水平线)被提取出来,并显示出来。这种处理可以用于线条检测、边缘提取等图像处理任务中。
效果展示
input image
gray image
vline image
result image
效果比较分析
在这段代码中,根据输入图像提取出了四个不同的图像,分别是原图像input image、灰度图像gray image、自适应阈值分割图像result image和垂直线图像vline image。
-
灰度图像:将输入图像转换为灰度图像。灰度图像展示了输入图像的亮度信息,将彩色图像转换为灰度图像可以简化图像处理过程。
-
自适应阈值分割图像:对灰度图像进行自适应阈值分割,将图像转换为二值图像。自适应阈值分割是一种根据图像局部区域灰度值自适应地确定阈值的方法,适用于图像中存在光照变化的情况。
-
垂直线图像:应用形态学开操作,提取出输入图像中的垂直线。在此处使用的核是垂直方向的矩形,通过腐蚀和膨胀操作,将图像中的垂直线进行提取。
比较分析:
- 灰度图像展示了输入图像的亮度信息,可以较好地反映图像的纹理和细节;
- 自适应阈值分割图像可以将图像转换为二值图像,将一些背景变为黑色、目标物体变为白色,通过阈值分割可以提取出兴趣区域;
- 垂直线图像突出显示了输入图像中的垂直线,可以辅助进行线条检测和边缘提取等任务;
通过比较这四个图像的特点和效果,我们可以根据实际需求选择合适的图像进行进一步的处理和分析。
结论
这段代码展示了一种图像处理的流程和方法,通过对图像进行灰度化、自适应阈值分割和形态学操作,成功提取出图像中的垂直线条。通过代码的运行结果,可以得出结论:代码能够较好地将垂直线条从原始图像中提取出来,但最终的效果还需根据具体情况进行进一步调整和优化。