代码很多都参考了 小白YouCans ,感谢这位博主。
环境使用 Kaggle 里免费建立的 Notebook。
%matplotlib inline
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
因为使用的是 Notebook,如果使用 cv.imshow(img)
,在 Pycharm 上运行会弹出一个窗口显示图片,但是在 Notebook 中会报错,所以使用 %matplotlib inline
和 plt.imshow(img)
可以让代码块执行后直接在下面输出图像。
添加图片数据集:
按照 URL 搜索,Add 添加即可,数据集地址:https://www.kaggle.com/datasets/xenxiou/common-pictures-of-opencv:
实现打开一幅图片,完成对图像数据的读取,存储和显示。
cv.imread
默认读入的矩阵是 BGR 格式的,定义一个函数转换为 RGB 格式:
def cv_imread(path):
img = cv.imread(path)
return cv.cvtColor(img, cv.COLOR_BGR2RGB)
img_path = '/kaggle/input/common-pictures-of-opencv/LenaRGB.bmp'
img = cv_imread(img_path)
plt.imshow(img)
cv.imwrite('./test.png', img)
图像的几何变换包括实现对图像数据的图像剪切、图像平移、图像旋转、图像镜像、图像的缩放,图像仿射功能。
https://zhuanlan.zhihu.com/p/80852438
imgCrop = img[150:400, 150:350]
plt.imshow(imgCrop)
# 图像平移
rows, cols, ch = img.shape
dx, dy = 100, 50 # dx=100 向右偏移量, dy=50 向下偏移量
MAT = np.float32([[1, 0, dx], [0, 1, dy]]) # 构造平移变换矩阵
dst = cv.warpAffine(img, MAT, (rows, cols), borderValue=(255,255,255)) # 设置白色填充
plt.imshow(dst)
theta = np.pi / 12 # 顺时针旋转角度
cosTheta = np.cos(theta)
sinTheta = np.sin(theta)
MAT = np.float32([[cosTheta, -sinTheta, 0], [sinTheta, cosTheta, 0]]) # 构造旋转变换矩阵
dst = cv.warpAffine(img, MAT, (cols, rows), borderValue=(255,255,255))
plt.imshow(dst)
imgFlip1 = cv.flip(img, 0) # 垂直翻转
imgFlip2 = cv.flip(img, 1) # 水平翻转
imgFlip3 = cv.flip(img, -1) # 水平和垂直翻转
tmp = np.hstack((imgFlip1, imgFlip2, imgFlip3))
plt.imshow(tmp)
imgZoom = cv.resize(img, (300, 200))
plt.imshow(imgZoom)
图像的基本处理包括实现图像灰度化、图像的二值化、图像的亮度和对比度的调整、图像的离散傅里叶变换功能。
# img2 = cv.imread(imgFile, flags=0) # flags=0 读取为灰度图像
imgGray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
plt.imshow(imgGray)
# 自适应二值化
dst = cv.adaptiveThreshold(imgGray,255,cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY,11,2)
plt.imshow(dst)
# 给定值二值化
_, dst = cv.threshold(imgGray, 127, 255, cv.THRESH_BINARY) # 转换为二值图像, thresh=127
plt.imshow(dst)
OpenCV中亮度和对比度应用这个公式来修改: g ( x ) = α f ( x ) + β g(x)=αf(x)+β g(x)=αf(x)+β,其中: α ( > 0 ) 、 β α(>0)、β α(>0)、β 常称为增益与偏置值,分别控制图片的对比度和亮度。
img_hsv = cv.cvtColor(img, cv.COLOR_RGB2HSV)
h,s,v = cv.split(img_hsv)
# 增加图像亮度
v1 = np.clip(cv.add(1*v,30),0,255)
# 增加图像对比度
v2 = np.clip(cv.add(2*v,0),0,255)
img1 = np.uint8(cv.merge((h,s,v1)))
img1 = cv.cvtColor(img1,cv.COLOR_HSV2RGB)
img2 = np.uint8(cv.merge((h,s,v2)))
img2 = cv.cvtColor(img2,cv.COLOR_HSV2RGB)
tmp = np.hstack((img, img1, img2))
plt.imshow(tmp)
# np.float32()将图像数据转换成float32 然后进行傅里叶变换cv2.dft()
dft = cv.dft(np.float32(imgGray),flags=cv.DFT_COMPLEX_OUTPUT)
# 将低频信息转换至图像中心
dft_shift = np.fft.fftshift(dft)
# 傅里叶变换后的数据是由实部和虚部构成的,需要进行转换成图像格式才能显示(0,255)
# cv2.magnitude()将实部和虚部转换为实部,乘以20将结果放大
magnitude_spectrum = 20 * np.log(cv.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))
plt.imshow(magnitude_spectrum)
图像边缘检测包括实现Canny算法边缘检测,Sobel算法边缘检测,Scharr滤波器算法边缘检测功能。
img_gs = cv.GaussianBlur(img,(3,3),0)
canny = cv.Canny(img_gs, 50, 150)
plt.imshow(canny)
kernSobelX = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) # SobelX kernel
kernSobelY = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]]) # SobelY kernel
imgSobelX = cv.filter2D(img, -1, kernSobelX, borderType=cv.BORDER_REFLECT)
imgSobelY = cv.filter2D(img, -1, kernSobelY, borderType=cv.BORDER_REFLECT)
SobelX = cv.Sobel(img, cv.CV_16S, 1, 0) # 计算 x 轴方向
SobelY = cv.Sobel(img, cv.CV_16S, 0, 1) # 计算 y 轴方向
absX = cv.convertScaleAbs(SobelX) # 转回 uint8
absY = cv.convertScaleAbs(SobelY) # 转回 uint8
SobelXY = cv.addWeighted(absX, 0.5, absY, 0.5, 0) # 用绝对值近似平方根
tmp = np.hstack((SobelX, SobelY, SobelXY))
plt.imshow(tmp)
# 使用函数 filter2D 实现 Scharr 算子
kernScharrX = np.array([[-3, 0, 3], [-10, 0, 10], [-3, 0, 3]]) # ScharrX kernel
kernScharrY = np.array([[-3, 10, -3], [0, 0, 10], [3, 10, 3]]) # ScharrY kernel
# 使用 cv.Scharr 实现 Scharr 算子
ScharrX = cv.Scharr(img, cv.CV_16S, 1, 0) # 计算 x 轴方向
ScharrY = cv.Scharr(img, cv.CV_16S, 0, 1) # 计算 y 轴方向
absX = cv.convertScaleAbs(ScharrX) # 转回 uint8
absY = cv.convertScaleAbs(ScharrY) # 转回 uint8
ScharrXY = cv.addWeighted(absX, 0.5, absY, 0.5, 0) # 用绝对值近似平方根
tmp = np.hstack((ScharrX, ScharrY, ScharrXY))
plt.imshow(tmp)
图像运算包括实现对图像的代数运算(加,减,乘,除)和逻辑运算(与,或,补)功能。
再导入一张图片:
img2 = cv_imread('/kaggle/input/common-pictures-of-opencv/BaboonRGB.bmp')
plt.imshow(img2)
加减乘除:
tmp = np.hstack((cv.add(img, img2),
cv.subtract(img,img2),
cv.multiply(img,img2),
cv.divide(img,img2)))
plt.imshow(tmp)
与补非:
tmp = np.hstack((cv.bitwise_and(img,img2),
cv.bitwise_or(img,img2),
cv.bitwise_not(img)))
plt.imshow(tmp)