首页IT科技opencv边缘检测算子(基于opencv的边缘检测方法)

opencv边缘检测算子(基于opencv的边缘检测方法)

时间2025-05-02 21:13:07分类IT科技浏览3332
导读:1、梯度运算 用OpenCV的形态变换( 膨胀、腐蚀、开运算和闭运算)函数morphologyEx...

1          、梯度运算

用OpenCV的形态变换( 膨胀               、腐蚀     、开运算和闭运算)函数morphologyEx

梯度运算即膨胀结果-腐蚀结果:

【注意】对于二值图像来说          ,必须是前景图像为白色               ,背景为黑色     ,否则需要进行反二值化处理 import cv2 import matplotlib.pyplot as plt import numpy as np ##读入图片 im1 = cv2.imread(r"fiction\xiaozhu.jpg", cv2.IMREAD_GRAYSCALE) #创建一个5行5列的值全为1 的卷积核 k = np.ones((5,5),np.uint8) ##进行梯度运算 r = cv2.morphologyEx(im1, cv2.MORPH_GRADIENT, k) ##图像展示 plt.subplot(1,2,1) plt.imshow(im1, cmap="gray") plt.axis("off") plt.subplot(1,2,2) plt.imshow(r, cmap= "gray") plt.axis("off") plt.show()

2     、sobel算子

可以计算不同方向的梯度          ,梯度运算如下图所示:

得出x方向的梯度值和y方向的梯度值后               ,通过G = sqr(GX2 + GY2)或G = |GX|+G|Y|得到整幅图像的梯度          。

cv2.Sobel参数:

【注意】

1               、如果梯度为负数     ,会无法显示     ,所以计算完梯度之后需要进行取绝对值处理               。

2          、同时计算x方向和y方向的梯度               ,通常没有分别计算两个方向梯度后          ,进行后处理效果好     ,通常用cv2.addWeighted(src1, alpha, src2, beta, gamma)进行修正     。

3     、卷积核大小只能为奇数     。 import cv2 import numpy as np im1 = cv2.imread(r"fiction\xiaozhu1.jpg",cv2.IMREAD_GRAYSCALE) ##默认卷积核为3*3               ,如果写cv2.Sobel(im1, 0, 1, 0)的话          ,只能取到一侧边界,另一侧边界值为负               ,会被规整成0 sobelx = cv2.Sobel(im1, cv2.CV_64F, 1, 0,ksize=3) sobely = cv2.Sobel(im1, cv2.CV_64F, 0, 1,ksize=3) ##取绝对值 cv2.convertScaleAbs(sobelx) sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0) ##同时取x               、y的sobel算子没有单独计算x          、y然后相加的效果好 sobel_tmp = cv2.Sobel(im1, cv2.CV_64F, 1, 1) cv2.convertScaleAbs(sobel_tmp) cv2.namedWindow("dx=1", 0) cv2.namedWindow("dy=1", 0) cv2.namedWindow("after addWeighted", 0) cv2.namedWindow("dx=1,dy=1", 0) cv2.imshow("dx=1", sobelx) cv2.imshow("dy=1", sobely) cv2.imshow("after addWeighted", sobelxy) cv2.imshow("dx=1,dy=1", sobel_tmp) cv2.waitKey(0) cv2.destroyAllWindows()

3、scharr算子

类似sobel算子               ,但是卷积核系数不同,离目标点越近的像素权重越大          ,边缘提取的效果比sobel算子好

二者效果对比如下: import cv2 im1 = cv2.imread(r"fiction\xiaozhu.jpg", cv2.IMREAD_GRAYSCALE) ##Scharr算子提取边缘,scharr相较于sobel算子               ,靠近核心部分的权值较大     ,边缘提取的效果更好          ,x与y不能同时为1 im1x = cv2.Scharr(im1, cv2.CV_64F, 1, 0) im1y = cv2.Scharr(im1, cv2.CV_64F, 0, 1) im1x = cv2.convertScaleAbs(im1x) im1y = cv2.convertScaleAbs(im1y) im1ScharryXY = cv2.addWeighted(im1x, 0.5, im1y, 0.5, 0) ##拉普拉斯算子 imLap = cv2.Laplacian(im1,cv2.CV_64F) imLap = cv2.convertScaleAbs(imLap) ##对比sobel算子提取边缘的效果 im1SobelX = cv2.Sobel(im1, cv2.CV_64F, 1, 0) im1SobelY = cv2.Sobel(im1, cv2.CV_64F, 0, 1) im1SobelX = cv2.convertScaleAbs(im1SobelX) im1SobelY = cv2.convertScaleAbs(im1SobelY) im1SobelXY = cv2.addWeighted(im1SobelX, 0.5, im1SobelY, 0.5, 0) ##sobel算子模拟scharr算子进行边缘提取 im1So_SC_X = cv2.Sobel(im1, cv2.CV_64F, 1, 0, -1) im1So_SC_Y = cv2.Sobel(im1, cv2.CV_64F, 0, 1, -1) im1So_SC_X = cv2.convertScaleAbs(im1So_SC_X) im1So_SC_Y = cv2.convertScaleAbs(im1So_SC_Y) im1So_SC_XY = cv2.addWeighted(im1So_SC_X, 0.5, im1So_SC_Y, 0.5, 0) cv2.namedWindow("im1ScharryXY", 0) cv2.namedWindow("im1SobelXY", 0) cv2.namedWindow("im1So_SC_XY", 0) cv2.namedWindow("imLap", 0) cv2.imshow("im1ScharryXY", im1ScharryXY) cv2.imshow("im1SobelXY", im1SobelXY) cv2.imshow("im1So_SC_XY", im1So_SC_XY) cv2.imshow("imLap", imLap) cv2.waitKey(0) cv2.destroyAllWindows()

依次为scharry算子               、sobel算子               、sobel仿scharry、拉普拉斯算子结果

4          、canny边缘检测

原理:

1               、高斯滤波去噪声

2     、平滑后的图像用sobel算子计算梯度,梯度方向如下图所示:

梯度方向一般都与边界垂直               ,

一般归类为四个方向:垂直          、水平     ,两个对角线

3               、去除所有非边界点

4     、滞后阈值

选取两个阈值     ,maxVal和minVal

5     、用法               ,其实就一个函数          ,cv2.Canny()

import cv2 im1 = cv2.imread(r"fiction\pig2.jpg", cv2.IMREAD_UNCHANGED) im1 = cv2.Canny(im1, 128, 256) im2 = cv2.Canny(im1, 0, 256) im3 = cv2.Canny(im1, 0, 128) im4 = cv2.Canny(im1, 0, 10) cv2.namedWindow("128_256",0) cv2.namedWindow("0_256",0) cv2.namedWindow("0_128",0) cv2.namedWindow("0_10",0) cv2.imshow("128_256",im1) cv2.imshow("0_256",im2) cv2.imshow("0_128",im3) cv2.imshow("0_10",im4) cv2.waitKey(0)

5               、拉普拉斯金字塔

原图像减去(原图->向下采样->向上采样)

两次采样后图像会被平滑

import cv2 im1 = cv2.imread(r"fiction\xiaozhu.jpg", cv2.IMREAD_GRAYSCALE) ##向下取样,长          、宽各变为1/2 im1Low = cv2.pyrDown(im1) ##向上取样     ,长     、宽各变为原来2倍,会变模糊 im1High = cv2.pyrUp(im1Low) ##拉普拉斯金字塔结果 lapPyr = im1-im1High cv2.namedWindow("im1Low",0) cv2.namedWindow("im1High",0) cv2.namedWindow("im1",0) cv2.namedWindow("lapPyr",0) cv2.imshow("im1",im1) cv2.imshow("im1Low",im1Low) cv2.imshow("lapPyr",lapPyr) cv2.imshow("im1High",im1High) cv2.waitKey(0) cv2.destroyAllWindows()

依次为原图               、向下取样一次          、向上取样、原图-向上取样结果

可多层构造拉普拉斯金字塔

5               、findContours

这是个轮廓检测的方法               ,注意          ,边缘和轮廓是不一样的,边缘不一定连续               ,但是轮廓是连续的               。

import cv2 o = cv2.imread(r"fiction\xiaozhu.jpg", cv2.IMREAD_GRAYSCALE) co = cv2.imread(r"fiction\xiaozhu.jpg", cv2.IMREAD_UNCHANGED) cco = co.copy() max_threshold,img = cv2.threshold(o,127,255,cv2.THRESH_BINARY) ##findcounters:原始图像               、轮廓检测方式(只检测外轮廓、等级树形式等)          、轮廓近似方式 ##查找               、绘制过程中会改变原图像 counters, hieraichy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) r = cv2.drawContours(co, counters, -1, (255,0,0),6) cv2.namedWindow("o", 0) cv2.namedWindow("r", 0) cv2.imshow("o", cco) cv2.imshow("r", r) cv2.waitKey(0) cv2.destroyAllWindows()

6     、高通滤波

利用傅里叶变换               ,将o转化为频域

低频为内部信息,高频为边缘信息

通过高通滤波器得到边缘信息 #低频为内部信息          ,高频为边缘信息 import cv2 import matplotlib.pyplot as plt import numpy as np o = cv2.imread(r"fiction\xiaozhu.jpg", cv2.IMREAD_GRAYSCALE) ##利用傅里叶变换               ,将o转化为频域,cv2.DFT_COMPLEX_OUTPUT返回双通道的结果     ,包含幅度和频率          ,第一个通道是实数部分               ,第二个通道为虚数部分 #dft = cv2.dft(np.float32(o), flags=cv2.DFT_COMPLEX_OUTPUT) dft = np.fft.fft2(o) #将频域0点移动到中心 dft1 = np.fft.fftshift(dft) # result = 20*np.log(cv2.magnitude(dft1[:,:,0], dft1[:,:,1])) # # plt.subplot(2,2,1) # plt.imshow(o, cmap="gray") # # plt.subplot(2,2,2) # plt.imshow(result,cmap="gray") # # plt.show() ##通过高通滤波器得到边缘信息 rows,cols = o.shape crow,ccols = int(rows/2),int(cols/2) dft1[crow-3:crow+30,ccols-30:ccols+30] = 0 ishift = np.fft.ifftshift(dft1) iimg = np.fft.ifft2(ishift) iimg = np.abs(iimg) plt.subplot(1,2,1) plt.imshow(o,cmap="gray") plt.subplot(1,2,2) plt.imshow(iimg,cmap="gray") plt.show()

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
vite-plugin-components(vite 运行项目报错 ‘axios/index.js‘ does not provide anexport named ‘default‘) web搜索引擎是人工智能吗知乎(Web 开发与搜索引擎优化,你应该选择哪一个?)