有关API的调用与解释、以及代码的理解已写在注释中
像素操作
import cv2 as cv
def show_add(src1,src2):
dst = cv.add(src1, src2) # cv.add方法
cv.imshow('add',dst)
def show_subtract(src1,src2):
dst = cv.subtract(src1, src2) # cv.add方法
cv.imshow('subtract',dst)
def show_divide(src1,src2):
dst = cv.divide(src1, src2) # cv.add方法
cv.imshow('divide',dst)
def show_multiply(src1,src2):
dst = cv.multiply(src1, src2) # cv.add方法
cv.imshow('multiply',dst)
src1 = cv.imread('E:\OpenCV\opencv\sources\samples\data\WindowsLogo.jpg')
src2 = cv.imread('E:\OpenCV\opencv\sources\samples\data\LinuxLogo.jpg')
cv.imshow('src1',src1)
cv.imshow('src2',src2)
show_add(src1,src2)
show_subtract(src2,src1) # 参数顺序影响结果
show_divide(src1,src2) # 使用很少。参数顺序影响结果
show_multiply(src1,src2)
cv.waitKey()
阈值处理
import cv2 as cv
src = cv.imread('E:\Chidanta.jpg', 0) #参数0代表读取灰度图
ret, thresh1 = cv.threshold(src, 127, 255, cv.THRESH_BINARY) # 二值化阈值处理
ret, thresh2 = cv.threshold(src, 127, 255, cv.THRESH_BINARY_INV)
ret, thresh3 = cv.threshold(src, 127, 255, cv.THRESH_TRUNC) # truncate(截取),大于阈值部分转为阈值
ret, thresh4 = cv.threshold(src, 127, 255, cv.THRESH_TOZERO) # 小于阈值部分转为0
ret, thresh5 = cv.threshold(src, 127, 255, cv.THRESH_TOZERO_INV)
cv.imshow('src',src)
images = [thresh1, thresh2, thresh3, thresh4, thresh5]
titles = ['binary', 'binary_inv', 'trunc', 'tozero', 'tozero_inv']
for i in range(5):
cv.imshow(titles[i],images[i])
cv.waitKey()
添加噪音
import cv2 as cv
import numpy as np
def clamp(pv):
"""防止溢出"""
if pv > 255:
return 255
elif pv < 0:
return 0
else:
return pv
def gaussian_noise_demo(image):
"""添加高斯噪声"""
h, w, c = image.shape
for row in range(0, h):
for col in range(0, w):
s = np.random.normal(0, 15, 3) # 产生随机数,每次产生三个
b = image[row, col, 0] # blue
g = image[row, col, 1] # green
r = image[row, col, 2] # red
image[row, col, 0] = clamp(b + s[0])
image[row, col, 1] = clamp(g + s[1])
image[row, col, 2] = clamp(r + s[2])
滤波
import cv2 as cv
import numpy as np
src = cv.imread('E:\Chidanta.jpg', 0)
# 均值滤波,中心值是周围点的均值
blur = cv.blur(src,(3,3)) # ksize用小括号表示大小,而并不是一个列表。blur:模糊
# 方框滤波,在选择归一化=True时结果与均值滤波相同
box = cv.boxFilter(src, -1, (3,3), normalize=True)
# 高斯滤波。实际上是改变了权重矩阵(卷积核),利用正态分布函数给出不同的权重
gauss = cv.GaussianBlur(src,(3,3), 1)
# 中值滤波。对于某元素的卷积核,按照大小排序,并取中值代替原值
median = cv.medianBlur(src , 5)
# 将图片横向拼接
dst = np.hstack((blur, box, gauss, median))
cv.imshow('show', dst)
cv.waitKey()
基本形态学函数
import cv2 as cv
import numpy as np
import matplotlib as plt
src = cv.imread('Chidanta.jpg', 0)
kernel = np.ones((5,5), np.uint8)
# 腐蚀
dst1 = cv.erode(src, kernel, iterations=1)
# 膨胀
dst2 = cv.dilate(src, kernel, iterations=1)
# 开运算:先腐蚀后膨胀,去刺儿后还原
opening = cv.morphologyEx(src, cv.MORPH_OPEN, kernel)
# 闭运算:先膨胀后腐蚀
closing = cv.morphologyEx(src, cv.MORPH_OPEN, kernel)
# 梯度运算:膨胀-腐蚀
gradient = cv.morphologyEx(src, cv.MORPH_GRADIENT, kernel)
# 礼帽:原图-腐蚀=刺儿
tophat = cv.morphologyEx(src, cv.MORPH_TOPHAT, kernel)
# 黑帽:膨胀-原图=原图的部分信息
blackhat = cv.morphologyEx(src, cv.MORPH_BLACKHAT, kernel)
images = [dst1, dst2, opening, closing, gradient, tophat, blackhat] # 每个图片是它的一个元素
titles = ['erode', 'dilate', 'open', 'close', 'gradient', 'tophat', 'blackhat']
for i in range(7):
cv.imshow(titles[i],images[i])
cv.waitKey()
cv.destroyAllWindows()
边缘检测
import cv2 as cv
import numpy as np
import matplotlib as plt
src = cv.imread('Chidanta.jpg', 0)
kernel = np.ones((5,5), np.uint8)
# sobel
sobelx = cv.Sobel(src, cv.CV_64F, 1, 0) # CV_64F是深度参数,它代表可以取负数
sobelx = cv.convertScaleAbs(sobelx) # 负数在图像显示时会阶段为0,因此取绝对值可以正确表示所有边界
sobely = cv.Sobel(src, cv.CV_64F, 0, 1)
sobely = cv.convertScaleAbs(sobely)
sobelxy = cv.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
cv.imshow('sobel',sobelxy)
# scharr算子的编程与sobel相同,只是kernel不同
# laplacian 二阶导下的求边缘算法,它不分dx、dy,对噪点十分敏感
laplacian = cv.Laplacian(src, cv.CV_64F)
cv.imshow('laplacian',laplacian)
# canny边缘检测
# 1.使用高斯滤波器平滑图像
# 2.计算梯度与方向
# 3.非极大值抑制(两种方法)
# 4.双阈值,minVal,与maxVal。抑制孤立的弱边缘
canny = cv.Canny(src,50,150)
cv.imshow('Canny',canny)
cv.waitKey()
cv.destroyAllWindows()
轮廓检测
import cv2 as cv
import numpy as np
import matplotlib as plt
src = cv.imread('University.jpg')
srcGray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(srcGray, 127, 255, cv.THRESH_BINARY) # 返回两个参数,否则会出问题
# 新版findContours返回两个参数,否则会报错not enough values to unpack
contours, hierarchy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) # hierarchy:等级
ini_src = src.copy() # 复制一份,防止drawContours覆盖
# 绘图,drawContours可以没有返回值,它直接就在src上画图了
cv.drawContours(src, contours, -1, (0,0,255), 3)
# 轮廓近似
# epsilon = 0.01*cv.arcLength(contours[0], True)
# approx = cv.approxPolyDP(contours, epsilon, True)
# cv.imshow('近似', approx)
cv.imshow('dst', src)
cv.waitKey()
cv.destroyAllWindows()
直方图
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
src = cv.imread(r'E:\PyCharm\OpenCV\University.jpg', 0)
plt.hist(src.ravel(),256) # 可以对图像直接进行求hist
# plt.show() # 如果一个文档有多个plt.show,则会有多个窗口显示,否则显示在一个窗口上
# 均衡化,
equ = cv.equalizeHist(src)
plt.hist(equ.ravel(),256)
plt.show() #在此处阻塞
# 自适应均衡化,其实就是将图像分块后均衡化,并在边界处进行线性插值
clahe = cv.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
# print(type(clahe)) #<class cv2.clahe>
res_clahe = clahe.apply(src)
cv.imshow('clahe', res_clahe)
cv.waitKey()