opencv 图像处理
255代表白色 0代表黑色
基本语法
def read_demo():
image = cv.imread('C:/Users/Administrator/Pictures/Camera Roll/1.jpg')
cv.imshow('input',image)
cv.waitKey(0)
cv.destroyAllWindows()
图像色彩 (滤镜)
def color_space_demo():
'''图像色彩'''
image = cv.imread('D:/tupian/2.jpg') #BGR,0-255
gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
hsv = cv.cvtColor(image,cv.COLOR_HSV2RGB) # H, 0-180
cv.imshow('gray', gray)
cv.imshow('hsv', hsv)
cv.waitKey(0)
# cv.namedWindow('input', cv.WINDOW_AUTOSIZE)
cv.destroyAllWindows()
结果如下
图像对象的创建与复制
def mat_demo():
'''图像对象的创建与复制'''
# image = cv.imread('D:/tupian/2.jpg',cv.IMREAD_GRAYSCALE) #灰度色彩,没有 C
image = cv.imread('D:/tupian/2.jpg')
# print(image)
print(image.shape) # (1024, 681, 3) H W C:代表通道
roi = image[100:200,100:200,:]
blank = np.zeros_like(image) #创建空白图像
blank[1:300, 100:300, 1:20] = image[1:300,100:300,1:20] # copy一部分image图像到空白图像blank上
#或者用zero
# h,w,c = image.shape
# blank = np.zeros((h,w,c),dtype=np.uint8)
# blank[1:300, 100:300, 1:20] = image[1:300, 100:300, 1:20] # copy一部分到空白图像
blank = np.copy(image) #全copy
cv.imshow('image', image)
cv.imshow('blank', blank)
# cv.imshow('roi', roi)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
对图像像素取反效果
def piexl_demo():
'''对图像像素取反效果'''
image = cv.imread('D:/tupian/2.jpg') #BGR,0-255
cv.imshow('start',image)
h,w,c = image.shape # 1024 681 3
print(image)
print(image[1,1])
for row in range(h):
for col in range(w):
b,g,r = image[row,col]
image[row, col] = (255-b,255-g,255-r) #像素取反效果
cv.imshow('result',image)
cv.imwrite('D:/tupian/2_bac.jpg',image) # 保存在本地
cv.waitKey(0)
# cv.namedWindow('input', cv.WINDOW_AUTOSIZE)
cv.destroyAllWindows()
结果如下
图像像素的算法操作 add subtract divide multiply
def math_demo():
'''图像像素的算法操作'''
image = cv.imread('D:/tupian/2.jpg') #BGR,0-255
blank = np.zeros_like(image) # 创建一个黑色的空白图像
print(cv.imshow('1', blank))
#255代表白色 0代表黑色
blank[:,:] = (2,2,2) #相当于 copy了一下空白图像,设置了其他颜色
result= cv.add(image,blank) # 加 这个result的像素对比image原图,像素更亮
result= cv.subtract(image,blank) #减 将原来的像素做减法 这个result的像素对比image原图,像素更暗
result1= cv.divide(image,blank) #除法 这个result的像素对比image原图,像素暗2倍
result1= cv.multiply(image,blank) # 乘法 这个result的像素对比image原图,像素亮2倍
cv.imshow('blank',blank)
cv.imshow('image',image)
cv.imshow('result',result)
cv.imwrite('D:/tupian/2_bac.jpg',image) # 保存在本地
cv.waitKey(0)
# cv.namedWindow('input', cv.WINDOW_AUTOSIZE) #根据图像大小调整窗口大小
cv.destroyAllWindows()
结果如下
TrackBar滚轮条操作调整图像亮度
def nothing(x):
print(x)
def adjust_lightness_demo():
image = cv.imread('D:/tupian/2.jpg')
cv.namedWindow('start',cv.WINDOW_AUTOSIZE) #根据图像调整窗口大小
cv.createTrackbar('lightness','start',0,100,nothing) #通过滑块修改亮度
cv.imshow('start',image)
blank = np.zeros_like(image)
while True:
pos = cv.getTrackbarPos('lightness','start')
blank[:,:] = (pos,pos,pos)
result = cv.add(image,blank)
cv.imshow('result',result)
c = cv.waitKey(1)
if c==27:
break
cv.destroyAllWindows()
结果如下
TrackBar滚动条同时调整亮度跟对比度
def nothing(x):
print(x)
def adjust_contrast_demo():
image = cv.imread('D:/tupian/2.jpg')
cv.namedWindow('start',cv.WINDOW_AUTOSIZE) #根据图像调整窗口大小
cv.createTrackbar('lightness','start',0,100,nothing) #通过滑块修改亮度
cv.createTrackbar('contrast','start',0,100,nothing) #通过滑块修改对比度
cv.imshow('start',image)
blank = np.zeros_like(image)
while True:
light = cv.getTrackbarPos('lightness','start')
contrast = cv.getTrackbarPos('contrast','start')/100
# blank[:,:] = (pos,pos,pos)
print('ll:',light,'co',contrast,'bl',blank,'im',image)
result = cv.addWeighted(image,contrast,blank,0.5,light)
cv.imshow('result',result)
c = cv.waitKey(1)
if c==27:
break
cv.destroyAllWindows()
结果如下
键盘操作像素
def key_demo():
image = cv.imread('D:/tupian/2.jpg')
cv.namedWindow('start',cv.WINDOW_AUTOSIZE)
cv.imshow('start',image)
while True:
c = cv.waitKey(1)
if c ==49: #代表按键盘数字 1
gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
cv.imshow('result',gray)
if c ==50: # 2
hsv = cv.cvtColor(image,cv.COLOR_BGR2HSV)
cv.imshow('result', hsv)
if c ==51: # 3
invert = cv.bitwise_not(image) #像素取反
cv.imshow('result', invert)
if c ==27: #退出
break
cv.destroyAllWindows()
opencv 自带颜色表 applyColorMap
例子:
def color_table_demo():
colormap = [
cv.COLORMAP_AUTUMN,
cv.COLORMAP_CIVIDIS,
cv.COLORMAP_COOL,
cv.COLORMAP_PARULA,
cv.COLORMAP_HOT,
cv.COLORMAP_BONE,
]
image = cv.imread('D:/tupian/2.jpg')
cv.namedWindow('start',cv.WINDOW_AUTOSIZE)
cv.imshow('start',image)
index = 0
while True:
dst = cv.applyColorMap(image,colormap[index%6]) #列表里有几个就% 几
index += 1
cv.imshow('color style',dst)
c = cv.waitKey(400)
if c ==27: #退出
break
cv.destroyAllWindows()
图像像素的逻辑操作 bitwise_and bitwise_or bitwise_not
def bitwise_demo():
b1 = np.zeros((400,400,3),dtype=np.uint8)
b1[:,:] = (255,0,255)
b2 = np.zeros((400, 400, 3), dtype=np.uint8)
b2[:, :] = (0, 255, 255)
cv.imshow('b1',b1)
cv.imshow('b2',b2)
dst1 = cv.bitwise_and(b1,b2)
dst2 = cv.bitwise_or(b1,b2)
cv.imshow('bitwise_and',dst1)
cv.imshow('bitwise_or',dst2)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
通道分离与合并 merge
def channels_split_demo():
image = cv.imread('D:/tupian/2.jpg')
cv.imshow('b',image)
cv.imshow('im',image[:,:,1])
mv = cv.split(image)
mv[2][:,:] = 25
result = cv.merge(mv)
dst = np.zeros(image.shape,dtype=np.uint8)
cv.mixChannels([image],[dst],fromTo=[2,0,1,1,0,2]) #转换通道
cv.imshow('dst',dst)
cv.imshow('re',result)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
图像色彩空间转换 inRange
def color_space_demo1():
#将图像先转成hsv,在bitwise_not 进行取反,
image = cv.imread('D:/tupian/3.jpg')
cv.imshow('image',image)
hsv = cv.cvtColor(image,cv.COLOR_BGR2HSV)
cv.imshow('hsv',hsv)
#RGB与HSV色彩空间转换,颜色inRange 生成mask轮廓提取与最大面积过滤
mask = cv.inRange(hsv,(35,43,46),(77,255,255)) #,过滤掉绿色,把人物抠出来
cv.imshow('mask', mask)
cv.bitwise_not(mask,mask) # 进行取反
result = cv.bitwise_and(image,image,mask=mask)
cv.imshow('re',result)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
图像像素值统计 meanStdDev
def pixel_stat_demo1():
image = cv.imread('D:/tupian/2.jpg')
cv.imshow('start',image)
max = np.max(image[:,:,2]) #计算第3通道的最大值 255
min = np.min(image[:,:,1]) #计算第2通道的最小值 0
means,dev = cv.meanStdDev(image) #统计均值和方差
print( 'mean',means,'dev',dev)
print(cv.meanStdDev(image)[0])
cv.waitKey(0)
cv.destroyAllWindows()
图像几何形状绘制 rectangle circle line
def drawing_demo():
b1 = np.zeros((512,512,3),dtype=np.uint8)
cv.rectangle(b1,(50,50),(400,400),(0,255,0),-1,4,0) #制作矩形 (图像,左上点,右下点,颜色,线的厚度, lineType=4 或者 8,shift点坐标中的小数位数) )
cv.circle(b1,(200,200),100,(255,0,255),4,2,0) #制作圆
cv.line(b1,(50,50),(400,400),(255,0,0),4,8,0) #制作线
cv.imshow('input',b1)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
绘制人脸
def drawing_demo():
# b1 = np.zeros((512,512,3),dtype=np.uint8)
b1 = cv.imread('D:/tupian/2.jpg')
cv.rectangle(b1,(200,200),(500,500),(0,255,0),8,4,0) #制作矩形 (图像,左上点,右下点,颜色,线的厚度, lineType=4 或者 8,shift点坐标中的小数位数) )
# putText(img,name,name的位置,字体,字体大小,字体颜色,线的厚度,lineType,)
cv.putText(b1,'99% face',(100,150),cv.FONT_HERSHEY_SIMPLEX,1.0,(255,0,255),2,8)
cv.imshow('input',b1)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
随机数与随机颜色 np.random.randint
def random_color_demo():
b1 = np.zeros((512,512,3),dtype=np.uint8)
while True:
xx = np.random.randint(0,512,2,dtype=np.int) #0-512之间随机取两个数
yy = np.random.randint(0,512,2,dtype=np.int)
bgr = np.random.randint(0,255,3,dtype=np.int32)
cv.line(b1,(xx[0],yy[0]),(xx[1],yy[1]),(np.int(bgr[0]),np.int(bgr[1]),np.int(bgr[2])),1,4,0)
cv.imshow('start',b1)
c = cv.waitKey(100)
if c==27:
break
cv.destroyAllWindows()
结果如下
多边形填充与绘制 drawContours
def polyline_drawing_demo():
canvas = np.zeros((512,512,3),dtype=np.uint8)
pts = np.array([[100,100],[200,350],[50,300],[100,300]],dtype=np.int)
pts1 = np.array([[100,10],[100,350],[100,30],[500,300]],dtype=np.int)
# cv.polylines(canvas,[pts],True,(0,255,255),2,4,0) #只能绘制多边形
# cv.fillPoly(canvas,[pts],(0,255,255),8,0) #只能填充多边形
#[pts] 代表可以填充多个轮廓
cv.drawContours(canvas,[pts,pts1],-1,(255,0,255),-1,) #填充&绘制多边形,最后一个-1 代表thinkness线的厚度,>0代表填充
cv.imshow('polyline',canvas)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
鼠标的操作
例: 使用鼠标框人头
# b1 = np.zeros((500,500,3),dtype=np.uint8)
b1 = cv.imread('D:/tupian/2.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_FLAG_LBUTTON: #鼠标按下
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,255,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, 255, 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()
结果如下
图像像素类型转换与归一化
def norm_demo():
img = cv.imread('D:/tupian/2.jpg')
cv.namedWindow('norm_demo',cv.WINDOW_AUTOSIZE)
result = np.zeros_like(np.float32(img))
cv.normalize(np.float32(img),result,0,1,cv.NORM_MINMAX,dtype=cv.CV_32F)
cv.imshow('norm_demo',np.uint8(result*255))
cv.waitKey(0)
cv.destroyAllWindows()
图像放缩与插值 resize
def resize_demo():
img = cv.imread('D:/tupian/2.jpg')
h,w,c = img.shape
# .resize(src,dst,Size(),0.5,0.5,插值)
# dst = cv.resize(img,(h//2,w//2),interpolation=cv.INTER_AREA)
# dst = cv.resize(img,(h*2,w*2),interpolation=cv.INTER_NEAREST)
dst = cv.resize(img,(0,0),fx=0.75,fy=0.75,interpolation=cv.INTER_NEAREST)
cv.imshow('resize_demo',dst)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
结果就是 可以调整图片大小
图像翻转
def flip_demo():
img = cv.imread('D:/tupian/2.jpg')
cv.imshow('img', img)
# cv.namedWindow('input',cv.WINDOW_AUTOSIZE)
dst = cv.flip(img,1) # 翻转 0,1,-1 三个值
cv.imshow('flip',dst)
cv.waitKey(0)
cv.destroyAllWindows()
图像旋转
教程链接: https://mp.weixin.qq.com/s/K4P8151BuM4DQPSK-KzPFQ
例1:使用自定义的M矩阵实现图像旋转
def rotate_demo():
src = cv.imread('D:/tupian/2.jpg')
cv.imshow('start',src)
h, w, c = src.shape
# 定义矩阵
M = np.zeros((2, 3), dtype=np.float32)
# 定义角度
alpha = np.cos(np.pi / 4.0)
beta = np.sin(np.pi / 4.0)
print("alpha : ", alpha)
# 初始化矩阵
M[0, 0] = alpha
M[1, 1] = alpha
M[0, 1] = beta
M[1, 0] = -beta
cx = w / 2
cy = h / 2
tx = (1 - alpha) * cx - beta * cy
ty = beta * cx + (1 - alpha) * cy
M[0, 2] = tx
M[1, 2] = ty
# 执行旋转
dst = cv.warpAffine(src, M, (w, h))
cv.imshow("rotate-center-demo", dst)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
例2 :重新计算旋转之后的图像大小,实现无Crop版本的图像旋转
def rotate_demo():
src = cv.imread('D:/tupian/2.jpg')
h, w, c = src.shape
M = np.zeros((2, 3), dtype=np.float32)
alpha = np.cos(np.pi / 4.0)
beta = np.sin(np.pi / 4.0)
print("alpha : ", alpha)
# 初始旋转矩阵
M[0, 0] = alpha
M[1, 1] = alpha
M[0, 1] = beta
M[1, 0] = -beta
cx = w / 2
cy = h / 2
tx = (1 - alpha) * cx - beta * cy
ty = beta * cx + (1 - alpha) * cy
M[0, 2] = tx
M[1, 2] = ty
# change with full size
bound_w = int(h * np.abs(beta) + w * np.abs(alpha))
bound_h = int(h * np.abs(alpha) + w * np.abs(beta))
# 添加中心位置迁移
M[0, 2] += bound_w / 2 - cx
M[1, 2] += bound_h / 2 - cy
dst = cv.warpAffine(src, M, (bound_w, bound_h))
cv.imshow("rotate ", src)
cv.imshow("rotate without cropping", dst)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
例3: 背景随便变化+无Crop版本的图像旋转动态演示
def rotate_demo():
src = cv.imread('D:/tupian/2.jpg')
h, w, c = src.shape
M = np.zeros((2, 3), dtype=np.float32)
degree = 1.0
d1 = np.pi / 180.0
while True:
alpha = np.cos(d1 * degree)
beta = np.sin(d1 * degree)
M[0, 0] = alpha
M[1, 1] = alpha
M[0, 1] = beta
M[1, 0] = -beta
cx = w / 2
cy = h / 2
tx = (1 - alpha) * cx - beta * cy
ty = beta * cx + (1 - alpha) * cy
M[0, 2] = tx
M[1, 2] = ty
# change with full size
bound_w = int(h * np.abs(beta) + w * np.abs(alpha))
bound_h = int(h * np.abs(alpha) + w * np.abs(beta))
M[0, 2] += bound_w / 2 - cx
M[1, 2] += bound_h / 2 - cy
red = np.random.randint(0, 255)
green = np.random.randint(0, 255)
blue = np.random.randint(0, 255)
dst = cv.warpAffine(src, M, (bound_w, bound_h), borderMode=cv.BORDER_CONSTANT, borderValue=(blue, green, red))
cv.imshow("rotate+background", dst)
c = cv.waitKey(1000)
if c == 27:
break
degree += 1
print("degree", degree)
if degree > 360:
degree = degree % 360
cv.imshow("rotate ", src)
cv.imshow("rotate without cropping", dst)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
视频文件& 摄像头使用 VideoCapture
def cideo_demo():
# cap = cv.VideoCapture(0) # 摄像头
cap = cv.VideoCapture('D:/s19day77/1.mp4') #读取视频文件
print(cap)
while True:
ret,frame = cap.read()
# frame = cv.flip(frame,1)
if ret is not True:
break
cv.imshow('frame',frame)
c = cv.waitKey(100)
if c ==27:
break
cv.destroyAllWindows()
视频处理与保存
def cideo_demo():
# cap = cv.VideoCapture(0) # 摄像头
cap = cv.VideoCapture('D:/s19day77/1.mp4') #读取视频文件
w = cap.get(cv.CAP_PROP_FRAME_WIDTH)
h = cap.get(cv.CAP_PROP_FRAME_HEIGHT)
fps = cap.get(cv.CAP_PROP_FPS) #1s播放9.900349765722959张图像
print(w,h,fps) #1360.0 768.0 9.900349765722959
# cv.VideoWriter.fourcc('P', 'I', 'M', '1') 代表编码,去官网兆对应的
# out = cv.VideoWriter('D:/test.mp4',cv.VideoWriter.fourcc('P','I','M','1'),fps,(np.int(w),np.int(h)),True)
# 或者可以写成通用的
out = cv.VideoWriter('D:/test.mp4',cv.CAP_ANY,np.int(cap.get(cv.CAP_PROP_FOURCC)),fps,(np.int(w),np.int(h)),True)
while True:
ret,frame = cap.read()
# frame = cv.flip(frame,1)
if ret is not True:
break
cv.imshow('frame',frame)
hsv = cv.cvtColor(frame,cv.COLOR_BGR2HSV) #将视频像素转成hsv的
cv.imshow('hsv', hsv)
out.write(hsv) #保存录像
c = cv.waitKey(100)
if c ==27:
break
cv.destroyAllWindows()
out.release()
cap.release()
图像直方图 calcHist
import matplotlip.pyplot as plt
def image_hist():
img = cv.imread('D:/tupian/2.jpg')
cv.imshow('input',img)
color = ('blue','red','green')
for i,color in enumerate(color):
hist = cv.calcHist(img,[i],None,[32],[0,256])
print(hist)
plt.plot(hist,color=color)
plt.xlim([0,256])
plt.show()
cv.waitKey(0)
cv.destroyAllWindows()
二维直方图
from matplotlib import pyplot as plt
def hist2d_demo():
img = cv.imread('D:/tupian/2.jpg')
hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV) # 将像素转成hsv
hist = cv.calcHist(hsv,[0,1],None,[48,48],[0,180,0,256])
dst = cv.resize(hist,(400,400))
cv.normalize(dst,dst,0,255,cv.NORM_MINMAX) #归一
cv.imshow('img',img)
dst = cv.applyColorMap(np.uint8(dst),cv.COLORMAP_JET)
cv.imshow('dst', dst)
plt.imshow(hist,interpoltion='nearest')
plt.title('2D Histogram')
plt.show()
cv.waitKey(0)
cv.destroyAllWindows()
直方图均衡化 equalizeHist
def eqhist_demo():
img = cv.imread('D:/tupian/2.jpg',cv.IMREAD_GRAYSCALE) #将图片转成灰度
cv.imshow('input',img)
result = cv.equalizeHist(img)
cv.imshow('result',result)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
图像卷积操作 (模糊操作) blur
def conv_demo():
img = cv.imread('D:/tupian/2.jpg')
cv.imshow('input',img)
result = cv.blur(img,(15,15))
cv.imshow('result', result)
cv.waitKey(0)
cv.destroyAllWindows()
结果如下
高斯模糊 GaussianBlur
def conv1_demo():
img = cv.imread('D:/tupian/2.jpg')
cv.imshow('input', img)
result = cv.GaussianBlur(img,(7,7),15) #ksize 必须是奇数
cv.imshow('result', result)
cv.waitKey(0)
cv.destroyAllWindows()
高斯双边模糊 bilateralFilter
def bifilter_demo():
img = cv.imread('D:/tupian/01.JPG')
cv.imshow('input', img)
result = cv.bilateralFilter(img,0,100,10)
cv.imshow('result', result)
cv.waitKey(0)
cv.destroyAllWindows()