OpenCV
—— Open Source Computer Vision
Python下使用示例:
图片篇
-
导入OpenCV
import cv2
-
读取图片与写图片
pic = cv2.imread(pic_path)#bgr格式,shape=(height, width, channel) cv2.imwrite(pic_path, pic)
注:cv2.imread返回一个[height, width, channel]的numpy.ndarray对象,height表示图片高度,width表示图片宽度,channel表示图片的通道。
-
调整尺寸
pic2 = cv2.resize(pic, (256, 256), interpolation=cv2.INTER_CUBIC)
-
图片分离成多通道,多通道合成图片
#通道分离 img_bgra = cv2.imread("sample.png",-1) b,g,r,a = cv2.split(img_bgra)
#通道合并 import numpy as np b_channel = np.ones((256, 256), dtype=np.uint8) * 0 g_channel = b_channel r_channel = b_channel image_bgr = cv2.merge((b_channel, g_channel, r_channel))
-
将三通道图转为单通道图(灰度图)
im_gray = cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
-
在图片上画圆/点
center = (int(x), int(y)) radius = 1 color = [0, 255, 255] cv2.circle(img_bgr, center, radius, color, -1)
-
图片仿射
cv2.warpAffine(src, affine_mat, size, dst, cv2.WARP_INVERSE_MAP, borderMode=cv2.BORDER_TRANSPARENT)
-
图片边界填充
output_bgr = cv2.copyMakeBorder(input_bgr, 1, 1, 1, 1, cv2.BORDER_ISOLATED | cv2.BORDER_CONSTANT, value=0)#用0填充上下左右边界1像素边界
-
返回最小的外接矩形
l, t, w, h = cv2.boundingRect(mask)#l为x起点,w为矩形宽(横向);t为y起点,h为矩形高(纵向)
-
在图片上画矩形
cv2.rectangle(img_bgr, (int(l), int(t)),(int(l+w), int(t+h)), (0, 255, 0), 1)
-
腐蚀/膨胀
erode_mask = cv2.erode(mask, cv2.getStructuringElement( cv2.MORPH_ELLIPSE, (3, 3)), iterations=1) dilate_mask = cv2.dilate(mask, cv2.getStructuringElement( cv2.MORPH_ELLIPSE, (3, 3)), iterations=1)
-
高斯模糊
blur_mask = cv2.GaussianBlur(mask, (3, 3), 0)
-
alpha融合
将两张图片src1和src2进行alpha融合(加权叠加)。dst=α⋅src1+β⋅src2+γ
src1 = cv2.imread(cv2.samples.findFile('LinuxLogo.jpg')) src2 = cv2.imread(cv2.samples.findFile('WindowsLogo.jpg')) alpha = 0.5#所有像素值均乘以0.5 beta = (1.0 - alpha) gamma = 0.0 dst = cv2.addWeighted(src1, alpha, src2, beta, gamma)
进阶:
cv2.multiply( )
,根据图片自带alpha蒙版融合src1 = cv2.imread('src1.png',-1)#读取bgra图片,alpha通道为自带蒙版(非上面固定的alpha = 0.5) src2 = cv2.imread('src2.jpg')#读取bgr图片 #通道分离 b,g,r,a = cv2.split(src1) #得到src1前景部分 src1_foreground = cv2.merge((b,g,r)) #得到src1的alpha蒙版 src1_alpha = cv2.merge((a,a,a)) #因为下面要进行乘法运算故将数据类型设为float,防止溢出 src1_foreground = src1_foreground.astype(float) src2 = src2.astype(float) #将alpha的值归一化在0-1之间,作为加权系数 src1_alpha = src1_alpha.astype(float)/255 #加权,每个像素的加权系数即为alpha蒙版对应位置像素的值 src1_foreground = cv2.multiply(src1_alpha,src1_foreground) src2 = cv2.multiply(1-src1_alpha,src2) outImage = src1_foreground + src2
-
图片拼接(需图片尺寸相同)
im = cv2.imread(pic_path)
im_hconcat = cv2.hconcat([im, im]) # 水平拼接,个数可以多个
im_vconcat = cv2.vconcat([im, im, im]) # 垂直拼接
视频篇
OpenCV集成了较完善的视频处理接口,不过由于OpenCV重点在于图像处理,因此可能不提供视频处理中某些常用的功能,例如视频生成的同时合并音频。如需这些视频处理的高级功能,建议使用FFmpeg。
-
读取视频文件
def cv2_read_video(video_file_path): """支持读取视频和GIF""" start = time.time() cap = cv2.VideoCapture(file_path) frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))#帧宽,横向 frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))#帧高,纵向 fps = cap.get(cv2.CAP_PROP_FPS) res = [] while True: ret, frame = cap.read() if ret is False: break res.append(frame) total_frames = len(res) cap.release() end = time.time() print('the video has total frames: ',total_frames) print('opencv read video use time: '+str(end-start)) return res, frame_width, frame_height, fps
Windows平台下还支持使用GPU解码读取视频:
import cv2 import time def load_material(file_path): """ Load a full list of frames in memory. """ cap = cv2.VideoCapture(file_path) frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fps = cap.get(cv2.CAP_PROP_FPS) res = [] while True: ret, frame = cap.read() if ret is False: break res.append(frame) material = res total_frames = len(res) cap.release() return material def load_material_cuda(file_path): """ Load a full list of frames in memory using cuda. """ cap = cv2.cudacodec.createVideoReader(file_path) # only support on Windows res = [] while True: ret, frame = cap.nextFrame() if ret is False: break res.append(frame.download()) material = res total_frames = len(res) cap.release() return material def main(file_path): t1 = time.time() material = load_material(file_path) t2 = time.time() print('opencv use cpu load material use: ', t2-t1) material2 = load_material_cuda(file_path) t3 = time.time() print('opencv use gpu load material use: ', t3-t2) if __name__ == '__main__': file_path = 'test.mp4' main(file_path)
-
写视频文件
def cv2_output_no_audio_video(output_imgs, output_file_path, fps, frame_size): """注:输出视频无音频""" size = frame_size start = time.time() fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') vout = cv2.VideoWriter() vout.open(output_file_path, fourcc, fps, size, True) for img in output_imgs: vout.write(img) vout.release() end = time.time() print('cv2_output_no_audio_video use time: '+str(end-start))
C++下使用示例:
图片篇
-
获取Mat的最大最小值
double minVal, maxVal; cv::minMaxIdx(compare_binaryMaskFloat, &minVal, &maxVal);
-
抽取多个通道(rgb)图片中的某通道
int coi = 0;//1, 2 cv::extractChannel(src, dst, coi)
参考资料:
[1] OpenCV-Python Tutorials
[2] LearnOpencv进阶系列一之Alpha通道混合
[3] OpenCV concat
[4] github - OpenCV-Python-Tutorial
[5] OpenCV-Python中文教程 · 看云
[6] FFmpeg常用命令小结
[7] OpenCV: Video I/O with OpenCV Overview
[8] opencv 颜色空间转换函数cvtColor()运用
[9] void cv::cuda::cvtColor
[10] void cv::cvtColor
[11] OpenCV: cv::VideoCapture Class Reference
[12] Learn OpenCV ( C++ / Python )
[13] void cv::extractChannel