openCV功能函数

形态学-腐蚀操作

cv2.erode(img, kernel, iterations=1)
img: 被处理图像
kernel: 处理图像用的盒子nxn大小
iterations: 函数运行次数

形态学-膨胀操作

cv2.dilate(img, kernel, iterations=1)

开运算和闭运算

开: 先腐蚀,再膨胀
cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv2.MORPH_OPEN: 开运算
闭: 先膨胀,再腐蚀
cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.MORPH_CLOSE: 闭运算

梯度运算

梯度 = 膨胀 - 腐蚀
cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

礼帽和黑帽

礼帽 = 原始输入 - 开运算结果
cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
黑帽 = 闭运算 - 原始输入
cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

图像梯度-Sobel算子

计算图像中像素点的梯度
cv2.Sobel(sec, ddepth, dx, dy, ksize)
ddepth: 图像的深度
dx和dy: 分别表示水平和竖直方向
ksize: 是Sobel算子的大小
白到黑是正数, 黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值
sobelx = cv2.Sobel(sec, cv2.CV_64F, ddepth, dx, dy, ksize)
cv2.convertScaleAbs(sobelx)
分别计算x和y,再求和
cv2.addWeigthed(sobely, dx, sobely, dy, 0)
sobelx: 水平方向梯度
sobely: 竖直方向梯度
不建议直接计算x和y

Scharr算子

与Sobel算子的区别就是,计算用的矩阵中的数值比sobel中的要大,计算出来的图像梯度更明显

laplacian算子

梯度变化更敏感,对噪音点会比较敏感

Canny边缘检测

  1. 使用高斯滤波器,以平滑图像,过滤噪音
  2. 计算图像中每个像素点的梯度强度和方向
  3. 应用非极大值抑制,以消除边缘检测带来的杂散响应
  4. 应用双阈值检测,来确定真实的和潜在的边缘
  5. 通过抑制孤立的弱边缘最终完成边缘检测
cv2.Canny(img, minVal, maxVal)
minVal和maxVal: 双阈值检测的参数
高斯滤波器:中间值比较大,边缘值比较小

在Canny检测中对高斯滤波器进行归一化处理

Canny中使用的是sobel算子
非极大值抑制:线性插值法,划分方向法
双阈值检测
  1. 梯度值>maxVal,则处理为边界
  2. minVal<梯度值<maxVal,连有边界点则保留,否则舍弃
  3. 梯度值<minVal,则舍弃

图像金字塔

  1. 高斯金字塔
    做图像特殊提取,
  2. 拉普拉斯金字塔
高斯金字塔

向下采样方法(缩小):从塔底到塔尖

cv2.pyrUp(img)
  1. 将Gi与高斯内核卷积
  2. 将所有偶数行和列去除
    向上采样方法(放大):从塔尖到塔底
cv2.pyrDown(img)
  1. 将图像在每个方向扩大为原来的两倍,新增的行和列以0填充
  2. 使用先前同样的内核(乘以4)与放大后的图像卷积,获得近似值
    注意:若先进行上采样,后进行下采样,得到的结果图像没有原始的图像效果好
拉普拉斯金字塔

Li = Gi - PyrUp(PyrDown(Gi))
拉普拉斯金字塔 = 原始图像 减去 原始图像先做向下采样后做向上采样

down = cv2.pyrDown(img)
down_up = cv2.pyrUp(down)
l_1 = img - down_up

图像轮廓检测

cv2.findContours(img, mode, method)
mode: 轮廓检索模式
	RETR_EXTERNAL: 只检索最外面的轮廓
	RETR_LIST: 检索所有的轮廓,并将其保存到一条链表当中
	RETR_CCOMP: 检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界
	RETR_TREE: 检索所有的轮廓,并重构嵌套轮廓的整个层次(常用)
method: 轮廓逼近方法
	CHAIN_APPROX_NONE: 以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)
	CHAIN_APPROX_SIMPLE: 压缩水平的,垂直的和倾斜的部分,也就是,函数只保留他们的终点部分

为了更高i的准确率,使用二值图像

img = cv2.imread('--.png') # 读入图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转为灰度图像
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BLNARY) # 二值转换
cv_show(thresh, 'thresh')
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) # 边缘检测
binary:二值检测结果
contours: list保存的轮廓信息
hierarchy:层级信息

绘制轮廓

# 传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
# 注意需要copy,要不原图会变
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2) # -1表示所有轮廓绘制, 2是线条的宽度
cv_show(res, 'res')

轮廓特征

# 计算轮廓面积
cnt = contours[0] # 把每个轮廓单独拿出来计算
cv2.contourArea(cnt)
# 计算周长
cv2.arcLength(cnt, True)

轮廓近似

epsilon = 0.1 * cv2.arcLength(cnt, True) # 用轮廓的周长的0.1倍作为阈值,阈值越小,得到的轮廓越接近原先的曲线轮廓
approx = cv2.approxPolyDP(cnt, epsilon, True)

绘制边界矩形

x, y, w, h = cv2.boundingRect(cnt) # 获取边缘矩形
img = cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) # 在原始图像当中绘制边界矩形
rect_area = w * h # 边界矩形面积
area = cv2.contourArea(cnt) # cnt轮廓面积
extend = float(area) / rect_area # 轮廓面积与边界矩形比

绘制外接圆

(x, y), radius = cv2.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
img = cv2.circle(img, center, radius, (0, 255, 0), 2)

模板匹配

模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度,这个差别程度的计算方法在opencv中有6种,然后将每次计算的结果放入一个矩阵中,作为结果输出。加入原图形是AB大小,而模板是ab大小,则输出结果的矩阵是(A - a + 1)* (B - b + 1)

TM_SQDIFF:计算平方不同,计算出来的值越小,越相关
TM_CCORR:计算相关性,计算出来的值越大,越相关
TM_CCOEFF:计算相关系数,计算出来的值越大,越相关
TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关
TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关
TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1,越相关
建议使用带归一化的方法
# 模板匹配
img = cv2.imread('--.jpg', 0)
template = cv2.imread('--.jpg', 0)
h, w = template.shape[:2]

res = cv2.matchTemplate(img, template, cv2.TM_SQDIFF) # 模板匹配
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(res) # 获取模板匹配不同匹配方式的结果,当前选择的是TM_SQDIFF, 应该选择minVal和minloc
多模板匹配
img_rgb = cv2.imread('---.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('---.jpg', 0)
h, w = template.shape[:2]

res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8 # 设置一个阈值,来找出多个符合阈值的目标点
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
    bottom_right = (pt[0] + w, pt[1] + h)
    cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)

cv2.imshow('img_rgb', img_rgb)
cv2.waitKey(0)

图像直方图统计

横坐标:0~255,纵坐标:个数

img = cv2.imread('---.jpg')
hist = cv2.calcHist([img], [0], None, [256], [0, 256])

plt.hist(img.ravel(), 256)
plt.show()

images: 原图像格式为uint8或float32. 当传入函数时应用中括号【】括起来
channels:同样用中括号括起来,如果入图像是灰度图就是[0], 如果是彩色图,传入的参数可以是[0][1][2],分别对应着BGR
mask:掩模图像,统计整幅图像的直方图就设置为None
histSize: BIN的数目
ranges:像素值范围常为[0, 256]
彩色图直方图统计
img = cv2.imread('---.jpg')
color = ('b', 'g', 'r')
for i, col in enumerate(color):
    hist = cv2.calcHist([img], [i], None, [256], [0, 256])
    plt.plot(hist, color=col)
    plt.xlim([0, 256])
创建mask掩码
# 创建mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
# 与操作
mask_img = cv2.bitwise_and(img, img, mask=mask)
直方图均衡化
equ = cv2.equalizeHist(img)
# equ是做完均衡化后的像素点
自适应直方图均衡化
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
res_clahe = clahe.apply(img)

傅里叶变换

傅里叶变换的作用
  1. 高频:变化剧烈的灰度分量,例如边界
  2. 低频:变化缓慢的灰度分量,例如一片大海
滤波
  1. 低通滤波器:只保留低频,会使得图像模糊
  2. 高通滤波器:只保留高频,会使得图像细节增强
    opencv中主要就是cv2.dft()和cv2.idft(),输入图像需要先转换成np.float32格式
    得到的结果中频率为0的部分会在左上角,通常要转换到中心位置,可以通过shift变换来实现
    cv2.dft()返回的结果是双通道的(实部和虚部),通常还需要转换成图像格式才能展示
低通滤波
img = cv2.imread('---.jpg')
img_float = np.float(img)
# dft
dft = cv2.dft(img_float, flags=cv2.DFT_COMPLEX_OUTPUT)
# shift变换,将结果移动到中心
dft_shift = np.fft.fftshift(dft)

rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2)

# 低通滤波
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 1

# 高通滤波
mask = np.ones((rows, cols, 2), np.uint8)
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 0

# idft
fshift = dft_shift * mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值