鼠标操作与响应
-
鼠标Callback函数
-
应用:使用鼠标进行矩形绘制
b1 = cv.imread(r"..\dataset\Image\The_Witcher_Lover.jpg")
img = np.copy(b1)
x1 = -1
x2 = -1
y1 = -1
y2 = -1
def mouse_drawing(event, x, y, falgs, param):
global x1, y1, x2, y2
if event == cv.EVENT_LBUTTONDOWN:
x1 = x
y1 = y
if event == cv.EVENT_MOUSEMOVE:
if x1 < 0 or y1 < 0:
return
x2 = x
y2 = y
dx = x2 - x1
dy = y2 - y1
if dx > 0 and dy > 0:
b1[:,:,:] = img[:,:,:]
cv.rectangle(b1, (x1, y1), (x2, y2), (0, 0, 255), 2, 8, 0)
if event == cv.EVENT_LBUTTONUP:
x2 = x
y2 = y
dx = x2 - x1
dy = y2 - y1
if dx > 0 and dy > 0:
b1[:,:,:] = img[:,:,:]
cv.rectangle(b1, (x1, y1), (x2, y2), (0, 0, 255), 2, 8, 0)
x1 = -1
x2 = -1
y1 = -1
y2 = -1
def mouse_demo():
cv.namedWindow("mouse_demo", cv.WINDOW_AUTOSIZE)
cv.setMouseCallback("mouse_demo", mouse_drawing)
while True:
cv.imshow("mouse_demo", b1)
c = cv.waitKey(10)
if c == 27:
break
cv.destroyAllWindows()
图像像素类型转换与归一化
- 归一化方法支持
- 归一化函数
cv.normalize(src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]] ) -> dst
src表示输入图像, dst表示输出图像,alpha, beta 默认是1, 0,是归一化的区间值
norm_type默认是NORM_L2,norm_type常用是NORM_MINMAX
- 注意:
def norm_demo():
image_uint8 = cv.imread(r"..\dataset\Image\The_Witcher_Lover.jpg")
cv.imshow("input", image_uint8)
img_f32 = np.float32(image_uint8)
cv.imshow("imgf32", img_f32)
cv.normalize(img_f32, img_f32, 1, 0, cv.NORM_MINMAX)
cv.imshow("norm_imgf32", img_f32)
cv.waitKey(0)
cv.destroyAllWindows()
图像几何变换
- 平移变换
- 放缩变换
- 旋转变换
- 旋转矩阵获取函数
cv.getRotationMatrix2D
Center表示旋转中心, angle表示度数,大于零表示逆时针旋转, scale表示放缩尺度大小
- 几个旋转操作函数
cv.flip(src, flipCode[, dst] ) ->dst
cv.rotate(src, rotateCode[, dst] ) -> dst
src表示输入图像
flipCode支持0水平、1垂直,-1对角线翻转,rotateCode支持旋转90°,180°,270°
def affine_demo():
image = cv.imread(r"..\dataset\Image\The_Witcher_Lover.jpg")
h, w, c = image.shape
cx = int(w / 2)
cy = int(h / 2)
cv.imshow("image", image)
M = np.zeros((2, 3), dtype=np.float32)
M[0, 0] = 3
M[1, 1] = 3
M[0, 2] = 0
M[1, 2] = 0
dst = cv.warpAffine(image, M, (int(w*3), int(h*3)))
cv.imshow("rescale-demo", dst)
M = cv.getRotationMatrix2D((w/2, h/2), 45.0, 1.0)
dst = cv.warpAffine(image, M, (w, h))
cv.imshow("rotate-demo", dst)
dst = cv.flip(image, 0)
cv.imshow("flip-demo", dst)
cv.waitKey(0)
cv.destroyAllWindows()
视频读写处理
- 视频标准与格式
SD(Standard Definition)标清480P
HD(High Definition)高清720P/1080P
UHD(Ultra High Definition)超高清4K/2160P
分辨率表示
SD-640x480, 704x480, 720x480, 848x480等
HD-960x720,1280x720,1440x1080,1920x1080
UHD-4K,2160P
- 视频读取函数
- 视频文件保存
cv.VideoWriter( filename, fource, fps, framesize[, isColor]-> <videoWriter object>
filename保存文件名称,fourcc编码方式,fps帧率,frameSize 视频帧大小,与实现大小相符
- 查询视频属性
def video_demo():
cap = cv.VideoCapture("vtest.avi")
# query video file metadata
fps = cap.get(cv.CAP_PROP_FPS)
frame_w = cap.get(cv.CAP_PROP_FRAME_WIDTH)
frame_h = cap.get(cv.CAP_PROP_FRAME_HEIGHT)
print(fps, frame_w, frame_h)
# encode mode
fourcc = cap.get(cv.CAP_PROP_FOURCC)
# create video writer
writer = cv.VideoWriter("output.mp4", int(fourcc), fps, (int(frame_w), int(frame_h)))
# loop read frame until last frame
while True:
ret, frame = cap.read()
if ret is not True:
break
cv.imshow("frame", frame)
c = cv.witKey(1)
if c == 27:
break
writer.write(frame)
图像直方图
- 图像直方图函数
hist = cv.calcHist([image], [i], None, [32], [0, 256])
image输入图像,i表示通道索引,mask=None,histSize表示bin的个数,表示通道的取值范围0~256
def image_hist():
image = cv.imread(r"..\dataset\Image\The_Witcher_Lover.jpg")
cv.imshow("input", image)
color = ('blue', 'green', 'red')
for i, color in enumerate(color):
hist = cv.calcHist([image], [i], None, [32], [0, 256])
print(hist)
plt.plot(hist, color=color)
plt.xlim([0, 32])
plt.show()
cv.waitKey(0)
cv.destroyAllWindows()
图像直方图均衡化
-
直方图均衡化原理
-
直方图均衡化函数
cv.equalizeHist(src[, dst]) -> dst
src必须是八位单通道图像,dst返回结果图像,类型与src保持一致
def eq_demo():
image = cv.imread(r"..\dataset\Image\The_Witcher_Lover.jpg", cv.IMREAD_GRAYSCALE)
cv.imshow("input", image)
hist = cv.calcHist([image], [0], None, [32], [0, 256])
print(hist.dtype)
plt.plot(hist, color="gray")
plt.xlim([0, 32])
plt.show()
cv.waitKey(0)
eqimg = cv.equalizeHist(image)
hist = cv.calcHist([eqimg], [0], None, [32], [0, 256])
print(hist.dtype)
plt.plot(hist, color="gray")
plt.xlim([0, 32])
plt.show()
cv.waitKey(0)
cv.destroyAllWindows()
图像卷积操作
- 图像卷积的定义
- 卷积的边缘填充
边缘处理,边缘填充的方式
cv.BORDER_DEFAULT gfedcb|abcdefgh|gfedcba
cv.BORDER_WRAP cdefgh|abcdefgh|abcdefg
cv.BORDER_CONSTANT iiiiii|abcdefgh|iiiiiii
- 卷积模糊函数
v.blur( src, ksize[, dst[, anchor[, borderType]]]) -> dst
src表示输入图像 CV_8U, CV_32F or CV_64F
Ksize卷积核大小
Anchor锚定位置
borderType边缘处理方式
def conv_demo():
image = cv.imread("lena.png")
dst = np.copy(image)
cv.imshow("input", image)
h, w, c = image.shape
for row in range(1, h-1, 1):
for col in range(1, w-1, 1):
m = cv.mean(image[row-2 : row+2, col-2:col+2])
dst[row, col] = (int(m[0]), int(m[1]), int(m[2]))
cv.imshow("conv-demo", dst)
blured = cv.blur(image, (5, 5), anchor=(-1, -1))
cv.imshow("blur-demo", blured)
cv.waitKey(0)
cv.destroyAllWindows()
高斯模糊
- 高斯模糊函数
cv.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]]) ->dst
ksize必须是正数而且是奇数
sigmaX高斯核函数X方向标准方差,sigmaY高斯核函数Y方向标准方差,默认0,表示跟sigmaX相同,
ksize为0表示从sigmaX计算生成ksize,ksize大于0表示从ksize计算生成sigmaX
- 均值模糊与高斯模糊
均值模糊 – 卷积核权重系数相同
高斯模糊 – 卷积核根据高斯函数生成,权重系数不同
def conv_demo():
image = cv.imread("lena.png")
cv.imshow("input", image)
g1 = cv.GaussianBlur(image, (0, 0), 15)
g2 = cv.GaussianBlur(image, (15, 15), 15)
cv.imshow("GaussianBlur-demo1", g1)
cv.imshow("GaussianBlur-demo2", g2)
cv.waitKey(0)
cv.destroyAllWindows()
像素重映射
- 像素重映射
把像素点P(x,y)重新映射到一个新的位置P’(x’, y’) - 像素重映射函数
cv.remap(src, map1, map2, interpolation[, dst[, borderMode[, borderValue]]] ) -> dst
src表示图像
map1表示x,y方向映射规则,或者x方向映射
map2如果map1表示x,y映射时为空,否则表示y
表示映射时候的像素插值方法,支持:INTER_NEAREST 、NTER_LINEAR 、NTER_CUBIC
def remap_demo():
image = cv.imread("lena.png")
cv.namedWindow("remap-demo", cv.WINDOW_AUTOSIZE)
cv.createTrackbar("remap-type", "remap-demo", 0, 3, trackbar_callback)
h, w, c = image.shape
cv.imshow("input", image)
map_x = np.zeros((h, w), dtype=np.float32)
map_y = np.zeros((h, w), dtype=np.float32)
while True:
pos = cv.getTrackbarPos("remap-type", "remap-demo")
#倒立
if pos == 0:
for i in range(map_x.shape[0]):
map_x[i, :] = [x for x in range(map_x.shape[1])]
for j in range(map_x.shape[1]):
map_y[:, j] = [map_y.shape[0] - y for y in range(map_y.shape[0])]
#镜像
elif pos == 1:
for i in range(map_x.shape[0]):
map_x[i, :] = [map_x.shape[1] - x for x in range(map_x.shape[1])]
for j in range(map_x.shape[1]):
map_y[:, j] = [y for y in range(map_y.shape[0])]
#对角线对称
elif pos == 2:
for i in range(map_x.shape[0]):
map_x[i, :] = [map_x.shape[1] - x for x in range(map_x.shape[1])]
for j in range(map_x.shape[1]):
map_y[:, j] = [map_y.shape[0] - y for y in range(map_y.shape[0])]
#放大两倍
elif pos == 3:
for i in range(map_x.shape[0]):
map_x[i, :] = [int(x/2) for x in range(map_x.shape[1])]
for j in range(map_x.shape[1]):
map_y[:, j] = [int(y/2) for y in range(map_y.shape[0])]
dst = cv.remap(image, map_x, map_y, cv.INTER_LINEAR)
cv.imshow("remap-demo", dst)
c = cv.waitKey(100)
if c == 27:
break
cv.waitKey(0)
cv.destroyAllWindows()
图像二值化
- 图像二值化的定义
图像二值化就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓,是一种简单的图像分割方法。
进行二值化有多种方式,其中最常用的就是采用阈值法(Thresholding)进行二值化。阈值法又分为全局阈值(Global Method)和局部阈值(Local Method),又称自适应阈值(Adaptive Thresholding)。
- 二值化函数
cv.threshold( src, thresh, maxval, type[, dst]) -> retval, dst
src表示输入图像,thresh表示阈值,maxval表示最大值
type表示二值化THRESH_BINARY或者二值化反THRESH_BINARY_INV
retval表示返回阈值,dst返回的二值图像
def binary_demo():
#灰度图像
image = cv.imread(r"..\dataset\Image\The_Witcher_Lover.jpg")
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("gray", gray)
#手动阈值,二值化
ret1, binary1 = cv.threshold(gray, 127, 255, cv.THRESH_BINARY)
cv.imshow("binary1", binary1)
#求均值,二值化
m = cv.mean(gray)[0]
ret2, binary2 = cv.threshold(gray, m, 255, cv.THRESH_BINARY)
cv.imshow("binary2", binary2)
cv.waitKey(0)
cv.destroyAllWindows()
全局与自适应二值化
- 全局二值化
OTSU法/大津法
三角法
图像处理之三角法图像二值化
cv.threshold( src, thresh, maxval, type[, dst])->retval, dst
type表示二值化
THRESH_BINARY | THRESH_OTSU
THRESH_BINARY | THRESH_TRIANGLE
THRESH_BINARY_INV | THRESH_OTSU
表示不同的全局二值化方法
- 自适应二值化
cv.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst] ) -> dst
cv.ADAPTIVE_THRESH_MEAN_C
cv.ADAPTIVE_THRESH_GAUSSIAN_C
blockSize必须为奇数
C表示要减去的权重,可以是正数,负数,0
def binary_demo():
#灰度图像
image = cv.imread(r"..\dataset\Image\The_Witcher_Lover.jpg")
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("gray", gray)
#大津法,
ret1, binary1 = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("otsu", binary1)
#三角法
ret2, binary2 = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
cv.imshow("triangle", binary2)
# 自适应法
binary3 = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 25, 10)
cv.imshow("adaptive", binary3)
cv.waitKey(0)
cv.destroyAllWindows()
实时人脸检测
- OpenCV3.3之前基于HAAR/LBP级联检测
OpenCV3.3开始支持深度学习人脸检测
支持人脸检测模型caffe/tensorflow
OpenCV4.5.4 支持人脸检测+landmark
模型下载地址:https://gitee.com/opencv_ai/opencv_tutorial_data - 相关函数
读取模型:readNetFromTensorflow
转换为blob对象:blobFromImage
设置输入:setInput
推理预测:forward