您现在的位置是:首页 >技术杂谈 >OpenCV 算法解析(一)网站首页技术杂谈
OpenCV 算法解析(一)
简介OpenCV 算法解析(一)
OpenCV 算法解析
1 图像增强
1.1 含义
突出图像细节,让图像更加清晰。
1.2 方法
直方图均衡
1.2.1 直方图均衡
直方图均衡
import cv2
import numpy as np
import matplotlib.pyplot as plt
def histequal(img_gray):
# 1 计算各个像素的频数、累积频数、归一化
h,w = img_gray.shape
cum_freq = np.array([(img_gray==i).sum() for i in range(255)]).cumsum()
cum_freq = (cum_freq/cum_freq[-1]*255).astype(np.uint8)
tmp = img_gray.copy()
for i in range(255):
tmp[img_gray == i] = cum_freq[i]
return tmp
img = cv2.imread('opencv/features/cat0.jpg', 0)
out = histequal(img)
plt.subplot(121)
plt.title('org')
plt.imshow( img,cmap='gray')
plt.subplot(122)
plt.title('histequal')
plt.imshow( out,cmap='gray')
plt.show()
1.2.2 gamma变换
import cv2
import numpy as np
import matplotlib.pyplot as plt
def gamma(img,c=2,r=2):
return np.array(c*img**r,dtype=np.uint8).clip(0,255)
img = cv2.imread('/Users/liushuang/Desktop/LearnGit/项目实战/鱼苗检测/yolov5-master/opencv/features/cat.jpg')
out = gamma(img)
plt.subplot(121)
plt.title('org')
plt.imshow( img,cmap='gray')
plt.subplot(122)
plt.title('gamma')
plt.imshow( out,cmap='gray')
plt.show()
2 除噪
2.1 含义
除去图片上的噪声
2.2 方法
空间滤波法(均值滤波、高斯滤波、中值滤波、双边滤波),变换滤波(傅立叶,小波变换)、形态学等
2.2.1 高斯滤波
高斯滤波
高斯滤波适合处理呈正态分布的噪声。滤波器的特点是权值成正态分布。方差越大,滤波效果越明显;反之,效果越差。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def guassian_filter(img, k_size=3, sigma=2):
# 获取通道
if len(img.shape) == 3:
h, w, c = img.shape
else:
img = np.expand_dims(img, axis=-1)
h, w, c = img.shape
# img padiing
pad = (k_size - 1) // 2
out_put = np.zeros((h + pad * 2, w + pad * 2,3), dtype=np.float32)
out_put[pad:pad + h, pad:pad + w] = img.copy().astype(np.float32)
# generate kernel
k = np.zeros((k_size, k_size), dtype = np.float32)
for i in range(-pad, k_size - pad):
for j in range(-pad, k_size - pad):
k[j + pad, i + pad] = np.exp(-(i ** 2 + j ** 2) / (2 * sigma ** 2))
k /= (2 * np.pi * sigma ** 2)
k /= k.sum()
tmp = out_put.copy()
# Gaussian filter
for i in range(h):
for j in range(w):
for cc in range(c):
out_put[pad + i, pad + j, cc] = np.sum(k * tmp[i:i + k_size, j:j + k_size, cc])
out_put = np.clip(out_put, 0, 255)
return out_put[pad:pad + h, pad:pad + w].astype(np.uint8)
#
img = cv2.imread('opencv/features/dogGauss.jpeg')
out = guassian_filter(img, k_size=3, sigma=2)
plt.subplot(121)
plt.title('org')
plt.imshow( img[...,::-1])
plt.subplot(122)
plt.title('out')
plt.imshow( out[...,::-1])
plt.show()
# sigma = 1 ,高斯核
'''
array([[0.07511362, 0.12384141, 0.07511362],
[0.12384141, 0.20417996, 0.12384141],
[0.07511362, 0.12384141, 0.07511362]], dtype=float32)
# sigma = 3
array([[0.10699731, 0.11310981, 0.10699731],
[0.11310981, 0.11957153, 0.11310981],
[0.10699731, 0.11310981, 0.10699731]], dtype=float32)
'''
2.2.2 均值滤波
### 2.2.2 mean+filter
import cv2
import numpy as np
import matplotlib.pyplot as plt
def mean_filter(img, k_size=3):
# shape
if len(img.shape) != 3:
img = img[..., None]
h, w, c = img.shape
# 1 kernel
k = np.ones((k_size, k_size), np.float32) / (k_size * k_size)
# 2 out_Put
pad = (k_size - 1) // 2
out_put = np.zeros((h + 2*pad, w + 2*pad, c), np.float32)
out_put[pad:pad + h, pad:pad + w] = img.copy().astype(np.float32)
# 3 filte
tmp = out_put.copy()
for i in range(h):
for j in range(w):
for cc in range(c):
out_put[pad + i:, pad + j, cc] = (tmp[i:i + k_size, j:j + k_size, cc] * k).sum()
out_put = np.clip(out_put, 0, 255)
return out_put[pad:pad + h, pad:pad + w].astype(np.uint8)
# filte
img = cv2.imread('opencv/features/dogGauss.jpeg')
out = mean_filter(img, k_size=3)
plt.subplot(121)
plt.title('org')
plt.imshow(img[..., ::-1])
plt.subplot(122)
plt.title('out_mean_filter')
plt.imshow(out[..., ::-1])
plt.show()
2.2.3 中值滤波
取窗口的中位数作为中心点的值,如果效果不好,可以增大核的尺寸,或者多循环几次。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def median_filter(img, k_size=10):
# shape
if len(img.shape) != 3:
img = img[..., None]
h, w, c = img.shape
# 2 out_Put
pad = (k_size - 1) // 2
out_put = np.ones((h + 2 * pad, w + 2 * pad, c), np.float32) * (-1)
out_put[pad:pad + h, pad:pad + w] = img.copy().astype(np.float32)
# 3 filte
tmp = out_put.copy()
for i in range(h):
for j in range(w):
for cc in range(c):
t = tmp[i:i + k_size, j:j + k_size, cc]
out_put[pad + i:, pad + j, cc] = np.median(t[t > 0])
return out_put[pad:pad + h, pad:pad + w].astype(np.uint8)
# filte
img = cv2.imread('opencv/features/letteropen.png')
out = median_filter(img, k_size=20)
plt.subplot(121)
plt.title('org')
plt.imshow(img[..., ::-1])
plt.subplot(122)
plt.title('median_filter')
plt.imshow(out[..., ::-1])
plt.show()
3 边缘检测
3.1 canny
canny 边缘检测流程
- 平滑处理
- 梯度检测
- 非极大值抑制
- 滞后阈值处理
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def canny(img):
# 1. 平滑
img_blur = cv.GaussianBlur(img, (5, 5), 2)
# 2. 梯度
gradx = cv.Sobel(img_blur, cv.CV_64F, 1, 0) # x
grady = cv.Sobel(img_blur, cv.CV_64F, 0, 1) # y
R = np.abs(gradx) + np.abs(grady)
T = np.arctan(grady / (gradx + 1e-3))
# 3. 非极大值抑制,细化边缘
h, w = R.shape
img_thin = np.zeros_like(R)
for i in range(1, h - 1):
for j in range(1, w - 1):
theta = T[i, j]
if -np.pi / 8 <= theta < np.pi / 8: # (-22,22)
if R[i, j] == max([R[i, j], R[i, j - 1], R[i, j + 1]]): # 上下
img_thin[i, j] = R[i, j]
elif -3 * np.pi / 8 <= theta < -np.pi / 8: # (-66,-22)
if R[i, j] == max([R[i, j], R[i - 1, j + 1], R[i + 1, j - 1]]): # 斜线
img_thin[i, j] = R[i, j]
elif np.pi / 8 <= theta < 3 * np.pi / 8: # (22,66)
if R[i, j] == max([R[i, j], R[i - 1, j - 1], R[i + 1, j + 1]]): # 反斜线
img_thin[i, j] = R[i, j]
else: # (66,110)
if R[i, j] == max([R[i, j], R[i - 1, j], R[i + 1, j]]): # 左右
img_thin[i, j] = R[i, j]
# 4 双阈值抑制
th1 = 5
th2 = 30
maxv = 255
img_edge = np.zeros_like(img_thin)
h, w = img_thin.shape
for i in range(1, h - 1):
for j in range(1, w - 1):
if img_thin[i, j] >= th2:
img_edge[i, j] = maxv
elif img_thin[i, j] > th1:
around = img_thin[i - 1:i + 2, j - 1:j + 2]
if around.max() >= th2:
img_edge[i, j] = maxv
return img_edge
img = cv2.imread('opencv/features/letteropen.png', 0)
out = canny(img)
plt.subplot(121)
plt.title('org')
plt.imshow( img,cmap='gray')
plt.subplot(122)
plt.title('canny')
plt.imshow( out,cmap='gray')
plt.show()
4 HOG特征提取
4.1 含义
通过提取图像局部区域梯度直方图构成特征,进而获取整个图像的特征。HOG对几何和光学形变都能保持不变形。通过局部归一化,忽略细节的变化,提取共哦那个特性。
4.2 流程
img --> cells,blocks --> 计算每个cell的梯度直方图
4.3 案例
6 两个比赛
6.1 三个功能整合
6.2 目标检测
6.3 yolov5代码详解
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。