本次是opencv学习的任务五,主要包含鼠标操作与响应、图像像素类型转换与归一化、图像几何变换、视频读写处理四部分学习内容。通过观看视频、了解相关功能的含义与API函数,再进行代码的实践,从理论到实践熟悉了解opencv,我对opencv有了更多的掌握。
注册回调函数:
void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0);
功能:为指定的窗口设置鼠标处理程序
参数:winname表示窗体的名称;onMouse表示鼠标事件的回调函数;param表示传递给回调函数的可选参数。
回调函数方法:
typedef void (MouseCallback)(int event, int x, int y, int flags, void userdata);
event是cv::MouseEventTypes 的常量之一;x是鼠标事件的x坐标,y鼠标事件的y坐标;flags是cv::MouseEventFlags 的常量之一;userdata 可选参数。
EVENT_LBUTTONDOWN、EVENT_MOUSEMOVE、EVENT_LBUTTONUP是三个非常重要的鼠标事件(MouseEventFlags ),分别表示鼠标左键按下,鼠标移动,鼠标左键弹起。
实验代码:
import cv2 as cv
import numpy as np
b1 = cv.imread("./apple.jpg")
img = np.copy(b1)
x1 = -1
x2 = -1
y1 = -1
y2 = -1
def mouse_drawing(event, x, y, flags, 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
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()
图像处理中,图像单通道像素值为0255之间的uchar类型,使用归一化将其转化为01区间之间可以在改变数据的分布和信息存储的前提下加速后续网络的计算。
归一化函数:void cv::normalize(InputArry src,InputOutputArray dst,double alpha=1,double beta=0,int norm_type=NORM_L2,int dtype=-1,InputArray mark=noArry())
参数:
src 输入数组;
dst 输出数组,数组的大小和原数组一致;
alpha 1表示用来规范值,2表示规范范围,并且是下限;
beta 规范范围并且是上限;
norm_type 归一化方法类型;
dtype 负值表示输出在大小深度通道数都等于输入,正值表示输出只在深度与输如不同,不同的地方由dtype决定;
mark 掩码。选择感兴趣区域,选定后只能对该区域进行操作。
数学公式类型:
NORM_MINMAX
NORM_INF
NORM_L1
NORM_L2
最常用 NORM_MINMAX
实验代码:
import cv2 as cv
import numpy as np
def trackbar_callback(pos):
print(pos)
image_uint8 = cv.imread("./butterfly.jpg")
cv.imshow("image_uint8", image_uint8)
img_f32 = np.float32(image_uint8)
cv.imshow("img32", img_f32)
cv.normalize(img_f32, img_f32, 1, 0, cv.NORM_MINMAX)
cv.imshow("norm-imgf32", img_f32)
cv.namedWindow("norm-demo", cv.WINDOW_AUTOSIZE)
cv.createTrackbar("normtype", "norm-demo", 0, 3, trackbar_callback)
while True:
dst = np.float32(image_uint8)
pos = cv.getTrackbarPos("normtype", "norm-demo")
if pos == 0:
cv.normalize(dst, dst, 1, 0, cv.NORM_MINMAX)
if pos == 1:
cv.normalize(dst, dst, 1, 0, cv.NORM_L1)
if pos == 2:
cv.normalize(dst, dst, 1, 0, cv.NORM_L2)
if pos == 3:
cv.normalize(dst, dst, 1, 0, cv.NORM_INF)
cv.imshow("norm-demo", img_f32)
c = cv.waitKey(50)
if c == 27:
break
cv.waitKey(0)
cv.destroyAllWindows()
实验结果:
(1)仿射变换:cv.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]] ) -> dst
src表示输入图像,M 表示2x3变换矩阵,dsize表示目标图像dst的大小,支持平移变换、放缩变换、旋转变换。
(2)旋转矩阵获取:cv.getRotationMatrix2D
Center表示旋转中心, angle表示度数,大于零表示逆时针旋转, scale表示放缩尺度大小。
(3)翻转:cv.flip(src, flipCode[, dst] ) ->dst
src表示输入图像,flipCode支持0水平、1垂直,-1对角线翻转。
(4)特殊角度旋转:cv.rotate(src, rotateCode[, dst] ) -> dst
src表示输入图像,rotateCode支持旋转90°,180°,270°。
(5)缩放函数:dst = cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
src表示输入图像, dst为缩放后的图像,fx,fy为图像x,y方向的缩放比例,interplolation为缩放时的插值方式,支持立方插值、双线形插值、最近邻插值、像素关系重采样等方法 。
实验代码:
import cv2 as cv
import numpy as np
image = cv.imread("./apple.jpg")
cv.imshow("apple", image)
h, w, c = image.shape
cx = int(w / 2)
cy = int(h / 2)
M = np.zeros((2, 3), dtype=np.float32)
M[0, 0] = .5
M[1, 1] = .5
M[0, 2] = 50
M[1, 2] = 50
print("M(2x3) = \n", M)
dst = cv.warpAffine(image, M, (cx, cy))
cv.imshow("translate-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,HD-960x720,UHD-4K等。
(1)视频读取函数:cv.VideoCapture(filename/Index,apiPreference ,params)
参数:filename表示视频文件,Index表示USB摄像头或者web camera的索引,apiPreference = CAP_ANY意思自动决定第三方视频库如 cv.CAP_FFMPEG、 cv.CAP_DSHOW。
(2)查看视频属性:VideoCaput的get方法
cv.CAP_PROP_FRAME_WIDT、cv.CAP_PROP_FRAME_HEIGHT、cv.CAP_PROP_FPS、cv.CAP_PROP_FOURCC、cv.CAP_PROP_FRAME_COUNT
(3)视频文件保存:cv.VideoWriter( filename, fourcc,fps, frameSize [, isColor] ) ->
filename表示保存文件名称,fourcc表示编码方式,fps表示帧率,frameSize表示视频帧大小,与实现大小相符。
实验代码:
import cv2 as cv
import numpy as np
cap = cv.VideoCapture("vtest.avi")
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)
fourcc = cap.get(cv.CAP_PROP_FOURCC)
writer = cv.VideoWriter("output.mp4", int(fourcc), fps, (int(frame_w), int(frame_h)))
while True:
ret, frame = cap.read()
if ret is not True:
break
cv.imshow("frame", frame)
c = cv.waitKey(1)
if c == 27:
break
writer.write(frame)
cv.waitKey(0)
cv.destroyAllWindows()
实验结果: