opencv
读取图片
image = cv2.imread('image.jpg') #原BGR格式
plt.imshow(image) #以RGB方式显示
plt.axis('off') #不显示坐标轴RGB
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB) #设置以RGB格式显示 (查看并改变通道方式)
plt.imshow(image)
plt.axis('off') #不显示坐标轴
cv2.imwrite("new_image2.jpg",image) #保存图片 最终以RGB保存,所以不能用cvtColor(改变了通道方式)
取某一像素
(b, g, r) = image[0,0] # image.shape (1440, 1080, 3) 取[0,0]的像素 对应有3个值
image[0,0] = (0, 0, 255) #赋值
取左上角图片
(h,w) = image.shape[:2] # h image.shape[0] , w image.shape[1]
cX, cY = (w//2,h//2)
tl = image[0:cY,0:cX] #取左上角图片(1/4)
plt.imshow(tl)
plt.axis('off')
image[0:cY,0:cX] = (0, 0, 255) #左上角图片变蓝
显示图片
def show(image):
plt.imshow(image)
plt.axis('off')
plt.show()
读取图片
def imread(image):
image = cv2.imread(image)
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
return image
平移 np.float32
image = imread('image.jpg')
(h,w) = image.shape[:2]
M = np.float32([[1,0,500],[0,1,500]]) #向右 向下
shifted = cv2.warpAffine(image, M, (w,h))
show(shifted)
旋转 cv2.getRotationMatrix2D
image = imread('image.jpg')
(h,w) = image.shape[:2]
(cX,cY) = (w/2,h/2)
M = cv2.getRotationMatrix2D((cX,cY), 45, 1.0)
# (cX,cY)-旋转中心点,45-逆时针旋转45度,1.0-缩放
#M = cv2.getRotationMatrix2D((cX+500,cY+500), 45, 1.0) #向左 向下
image = cv2.warpAffine(image, M, (w,h))
调整大小
width = 150
high = 150
#high = int(image.shape[0]*width/image.shape[1]) 等比例转换
image = cv2.resize(image, (width, high))
#image = cv2.resize(image, (width, high), interpolation=cv2.INTER_NEAREST) #算法
show(image)
print(image.shape)
人脸检测
image = imread('face.png')
# 级联分类器
detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
rects = detector.detectMultiScale(image, scaleFactor=1.1, minNeighbors=2, minSize=(10, 10), flags=cv2.CASCADE_SCALE_IMAGE)
for (x,y,w,h) in rects:
# 画矩形框
cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)
show(image)
人脸检测函数
def facedetect(image):
image = imread(image)
# 级联分类器
detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
rects = detector.detectMultiScale(image, scaleFactor=1.1, minNeighbors=2, minSize=(10, 10), flags=cv2.CASCADE_SCALE_IMAGE)
for (x,y,w,h) in rects:
# 画矩形框
cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)
show(image)
画图
image = np.zeros((300,300,3),dtype='uint8') #黑色图片
green = (0,255,0)
cv2.line(image, (0,0), (300,300), green) #绿线
blue = (0,0,255)
cv2.line(image, (300,0), (150,150), blue, 5) #线宽 5
#三角
red = (255,0,0)
cv2.rectangle(image, (10,10), (60,60), red, 2) #矩形
cv2.rectangle(image, (50,200), (220,280), green, -1) #填充
#画⚪
image = np.zeros((300,300,3),dtype='uint8')
(cX, cY) = image.shape[1]//2, image.shape[0]//2
white = (255,255,255)
for r in range(0,151,15):
cv2.circle(image, (cX,cY), r,(255,255,0), 2)
show(image)
#画随机⚪
image = np.zeros((300,300,3),dtype='uint8')
for i in range(10):
# 半径取值
radius = np.random.randint(5,200)
# 颜色取值
color = np.random.randint(0,255,size=(3,)).tolist()
# 圆心取值
pt = np.random.randint(0,300,size=(2,))
# 画图
cv2.circle(image, tuple(pt), radius, color, -1)
show(image)
翻转
image = cv2.flip(image,1) #1代表水平 0代表垂直 -1水平+垂直
加法
# 图像加法
print(cv2.add(np.uint8([200]),np.uint8([100]))) #[[255]] 最大255
# 普通加法
print(np.uint8([200])+np.uint8([100])) #255+1=0 [44]
减法
# 图像减法
print(cv2.subtract(np.uint8([50]),np.uint8([100]))) #[[0]]
# 普通减法
print(np.uint8([50])-np.uint8([100])) #50-1=255 [206]
变亮
image = imread('test.jpg')
# 生成跟图片形状相同的并且全为100的数据
M = np.ones(image.shape, dtype='uint8')*100
# 所有的像素加100
image = cv2.add(image, M)
#image = cv2.subtract(image, M) #变暗
show(image)
按位
rectangle = np.zeros((300,300,3),dtype='uint8')
white = (255,255,255)
cv2.rectangle(rectangle, (25,25), (275,275), white, -1) #三角
circle = np.zeros((300,300,3), dtype='uint8')
cv2.circle(circle, (150,150), 150, white, -1) #⚪
# AND,与操作,有黑就变黑
image = cv2.bitwise_and(rectangle, circle)
# OR,或操作,有白就变白
image = cv2.bitwise_or(rectangle, circle)
# XOR,异或操作,黑白变白,黑黑和白白变黑 相同变黑
image = cv2.bitwise_xor(rectangle, circle)
# NOT, 非操作,颜色取反
image = cv2.bitwise_not(circle)
遮挡
mask = np.zeros(image.shape,dtype='uint8')
white = (255,255,255)
cv2.rectangle(mask, (50,50), (250,350), white, -1) #相框
masked = cv2.bitwise_and(image, mask)
mask = np.zeros(image.shape,dtype='uint8')
white = (255,255,255)
cv2.circle(mask, (150,100), 80, white, -1) #⚪
切分,合并
(R, G, B) = cv2.split(image)
merged = cv2.merge([R,G,B])
图像金字塔
同一图像的不同分辨率的子图集合
cv2.pyrDown() 和 cv2.pyrUp() 构建图像金字塔
cv2.pyrDown(image)
cv2.pyrUp(image)
拉普拉斯金字塔: 𝐿𝑖=𝐺𝑖−𝑝𝑦𝑟𝑈𝑝(𝐺𝑖+1)
down_image1 = cv2.pyrDown(image)
down_image2 = cv2.pyrDown(down_image1)
up_image = cv2.pyrUp(down_image2)
laplacian = down_image1-up_image
腐蚀 黑色的部分变得更加大
# 矩形
kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) #morph 变形
# 椭圆
kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
# 十字形
kernel3 = cv2.getStructuringElement(cv2.MORPH_CROSS, (5,5))
for i in range(3):
erosion = cv2.erode(image, kernel3, iterations=i+1) #iterations腐蚀次数
show(erosion) #黑色的部分变得更加大
膨胀 白色的部分变得更加大
for i in range(3):
dilation = cv2.dilate(image, kernel1, iterations=i+1) #白色的部分变得更加大
show(dilation)
开运算 去除白点
先腐蚀后膨胀
image2 = imread('image2.jpg')
# 去除白点
opening = cv2.morphologyEx(image2, cv2.MORPH_OPEN, kernel1)
闭运算 去除黑点
先膨胀后腐蚀
# 去除黑点
closing = cv2.morphologyEx(image2, cv2.MORPH_CLOSE, kernel1)
先开后闭
opening = cv2.morphologyEx(image2, cv2.MORPH_OPEN, kernel1)
closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel1)
梯度 物体的轮廓
得到物体的轮廓
gradient = cv2.morphologyEx(image, cv2.MORPH_GRADIENT, kernel1) #dilation - erosion
顶帽/白帽 去除掉的白色部分
被去除掉的白色部分
tophat = cv2.morphologyEx(image2, cv2.MORPH_TOPHAT, kernel1)# #src - opening
黑帽 去除掉的黑色部分
被去除掉的黑色部分
blackhat = cv2.morphologyEx(image2, cv2.MORPH_BLACKHAT, kernel1) #closing - src
图像平滑
# 平均平滑
blur = cv2.blur(image, kernel)
blur = cv2.GaussianBlur(image, kernel, 0) #高斯模糊 0 标准差 方框中心的值最大
blur = cv2.medianBlur(image, kernel) #中值模糊 卷积框对应像素的中值来替代中心像素的值。
#双边滤波 能在保持边界清晰的情况下有效的去除噪音
blur = cv2.bilateralFilter(image, diameter,sigmaColor,sigmaSpace)
灰度
image = cv2.imread('image.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
cv2.imshow('original',image)
cv2.imshow('gray',gray) #后面要加gray
cv2.waitKey(0)
# waitKey的功能是等待一定的时间,如果等待时间内有按键操作就继续执行后面的语句,如果没有按键就在等待时间到后继续执行后面的语句。时间以ms为单位。waitKey参数为0的时候窗口不会自动关闭,无限等待按键
cv2.destroyAllWindows()
二值化
把图片传换成只有white和black这两种颜色
plt.imshow(gray,'gray') #前面为数据 后面为方式
cv2.imshow('gray2',gray2) #前面为标题 展示出来
ret1,thresh1 = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) #阈值 最大值
ret2,thresh2 = cv2.threshold(gray,127,255,cv2.THRESH_BINARY_INV)
ret3,thresh3 = cv2.threshold(gray,127,255,cv2.THRESH_TRUNC)
ret4,thresh4 = cv2.threshold(gray,127,255,cv2.THRESH_TOZERO)
ret5,thresh5 = cv2.threshold(gray,127,255,cv2.THRESH_TOZERO_INV)
plt.imshow(thresh1,'gray')
自动选择阈值
image = imread('image/opencv_logo.png')
ret1,thresh1 = cv2.threshold(gray,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)
plt.imshow(thresh1,'gray')
plt.axis('off')
plt.show()
自适应阈值
image = imread('image/license_plate.png')
image = cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
# 平均值阈值
th2 = cv2.adaptiveThreshold(image,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,3)
# 高斯阈值
th3 = cv2.adaptiveThreshold(image,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,3)
#11 邻域大小(用来计算阈值的区域大小)。 阈值就等于平均值或者加权平均值减去这个常数 3
plt.imshow(thresh2,'gray')
plt.axis('off')
plt.show()
梯度
def gradient(image):
image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
# cv2.CV_64F输出图像的深度(数据类型),64位float类型,因为梯度可能是正也可能是负
laplacian = cv2.Laplacian(image, cv2.CV_64F)
# 1, 0表示在x方向求一阶导数,最大可以求2阶导数
sobelx = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
# 0, 1表示在y方向求一阶导数,最大可以求2阶导数
sobely = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
titles = ['Original', 'Laplacian', 'SobelX', 'SobelY']
images = [image,laplacian,sobelx,sobely]
plt.figure(figsize=(10,5))
for i in range(4):
plt.subplot(2,2,i+1)
plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.axis('off')
plt.show()
Canny边缘检测
def edge_detection(image,minVal=100,maxVal=200): #阈值(100~200)
image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
edges = cv2.Canny(image,minVal,maxVal)
plt.imshow(edges,'gray')
plt.axis('off')
plt.show()
# 自动确定阈值的一种方法
def auto_canny(image, sigma=0.33):
v = np.median(image)
lower = int(max(0, (1.0-sigma) * v))
upper = int(min(255, (1.0+sigma) * v))
edged = cv2.Canny(image, lower, upper)
print(lower,upper)
return edged
摄像头读取
import numpy as np
import cv2
# 从摄像头获取图像数据
cap = cv2.VideoCapture(0)
while(True):
# ret 读取成功True或失败False
# frame读取到的图像的内容
# 读取一帧数据
ret,frame = cap.read()
# 变为灰度图
# gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
cv2.imshow('frame',frame)
# waitKey功能是不断刷新图像,单位ms,返回值是当前键盘按键值
# ord返回对应的ASCII数值
if cv2.waitKey(1)& 0xFF == ord('q'): # 0xFF 把返回值限制在在0和255之间
break
cap.release()
cv2.destroyAllWindows()
# 从文件读取视频内容
cap = cv2.VideoCapture('videos/cats.mp4')
# 视频每秒传输帧数
fps = cap.get(cv2.CAP_PROP_FPS)
# 视频图像的宽度
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
# 视频图像的长度
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
while(True):
# ret 读取成功True或失败False
# frame读取到的图像的内容
# 读取一帧数据
ret,frame = cap.read()
if ret!=True: #播放完关闭
break
cv2.imshow('frame',frame)
# waitKey功能是不断刷新图像,单位ms,返回值是当前键盘按键值
# ord返回对应的ASCII数值
if cv2.waitKey(25) & 0xff == ord('q'): #25 调整合适速度
break
cap.release()
cv2.destroyAllWindows()
视频写入
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('videos/output2.avi',fourcc,fps,(frame_width,frame_height))
while(True):
ret, frame = cap.read()
if ret==True:
# 水平翻转
frame = cv2.flip(frame,1)
out.write(frame)
# cv2.imshow('frame',frame)
# if cv2.waitKey(25) & 0xff == ord('q'):
# break
else:
break
out.release()
cap.release()
cv2.destroyAllWindows()
人脸检测
Haar特征+Adaboost级联分类器
色矩形所有像素值的和减去白色矩形所有像素值的和
# 级联分类器 人脸检测的模型 6061个特征 38个阶段
detector = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
rects = detector.detectMultiScale(image, scaleFactor=1.1, minNeighbors=2, minSize=(10,10), flags=cv2.CASCADE_SCALE_IMAGE)
for (x,y,w,h) in rects: #检测多少个脸,画多少个框
# 画矩形框
cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)
show(image)
函数
def facedetect(image):
image = imread(image)
# 级联分类器
detector = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
rects = detector.detectMultiScale(image, scaleFactor=1.1, minNeighbors=2, minSize=(10,10), flags=cv2.CASCADE_SCALE_IMAGE)
for (x,y,w,h) in rects:
# 画矩形框
cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)
show(image)
文件操作
创建文件
output2='predict_faces/anglababy2'
os.makedirs(output2)
for files in os.listdir('faces/anglababy'): #查看当前路径下的所有文件
print(files)
采集人脸样本
# 人脸检测并保存人脸
def facedetect(image, output):
# 获取文件名
name = os.path.basename(image)
# 读入图片
image = cv2.imread(image)
# 变成灰度图
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 级联分类器,检测人脸
detector = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml")
rects = detector.detectMultiScale(image, scaleFactor=1.1, minNeighbors=3, minSize=(20, 20), flags=cv2.CASCADE_SCALE_IMAGE)
# 循环每个人脸
for (x,y,w,h) in rects:
# 截取人脸,并且都转化为200*200的固定大小
f = cv2.resize(image[y:y+h, x:x+w], (200,200))
# 写入指定路径
cv2.imwrite(os.path.join(output, name), f)
# 检测并截取人脸
def predict_face(path, output):
# 如果该文件夹不存在则创建文件夹
if not os.path.exists(output):
os.makedirs(output)
# 循环每个人物的文件夹下的图片
for files in os.listdir(path):
# 检测是不是文件夹
if os.path.isdir(os.path.join(path, files)): #path下面的各个文件路径
# 定义截取到的人脸的输出路径
output2 = os.path.join(output, files) #output下面的各个文件路径
# 如果该文件夹不存在则创建文件夹
if not os.path.exists(output2): #创建
os.makedirs(output2)
# 人物文件夹的完整路径
files = os.path.join(path, files)
# 循环每个人的每张照片
for file in os.listdir(files):
# 照片完整路径
file = os.path.join(files, file)
# 检测人脸并保存
facedetect(file, output2)
生成label文件
for root, dirs, files in os.walk('predict_faces'):
print('r',root) #包括自己的所有文件夹 str
print('d',dirs) #文件夹 list
print('f',files) #文件 list
# 生成label文件
def get_label(path):
fh = open("label.txt", 'w')
# 表示人脸label
label = 0
for root, dirs, files in os.walk(path):
# 循环每个文件夹
for subdir in dirs: #root中所有文件
# 文件夹完整路径
subdir_path = os.path.join(root,subdir)
# 循环每个人物文件夹下面每张照片
for file in os.listdir(subdir_path):
# 照片完整路径
filepath = os.path.join(subdir_path, file)
# 判断文件类型是不是图片类型
imgType = imghdr.what(filepath)
if imgType == 'jpeg' or imgType == 'png':
# 保存图片路径
fh.write(filepath);
fh.write(";")
# 标签
fh.write(str(label))
fh.write("\n")
# 每个人的标签不一样,从0开始计数
label = label + 1
fh.close()
训练自己的数据模型
# 保存图片数据
images = []
# 保存标签
labels = []
# 打开文件
fh = open("label.txt")
# 循环每一行
for line in fh:
# 以;切分字符串
arr = line.split(";")
# 第0部分为图片路径,读取文件
img = cv2.imread(arr[0],0)
# 保存图片数据
images.append(img)
# 保存对应的标签数据
labels.append(int(arr[1]))
# 安装opencv扩展包
# pip install opencv-contrib-python
# 定义人脸识别模型
model = cv2.face.EigenFaceRecognizer_create()
# model = cv2.face.FisherFaceRecognizer_create()
# model = cv2.face.LBPHFaceRecognizer_create()
# 训练模型
model.train(np.array(images), np.array(labels))
# 保存模型
model.save("predict_face_XiaoMing_AB.xml")
人脸识别
# 定义人物名字
name= ['ab','xiaoming']
# 定义人脸识别模型
model = cv2.face.EigenFaceRecognizer_create()
# 载入训练好的模型
model.read('predict_face_XiaoMing_AB.xml')
# 读入测试图片来做测试
for file in os.listdir('test'):
file = os.path.join('test', file)
# 判断文件类型
imgType = imghdr.what(file)
if imgType == 'jpeg' or imgType == 'png':
# 读入图片
image = imread(file)
# 变为灰度图
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# 级联分类器
detector = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml")
rects = detector.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=3, minSize=(20, 20), flags=cv2.CASCADE_SCALE_IMAGE)
# 循环每个人脸
for (x,y,w,h) in rects:
# 画矩形框
cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)
# 人脸识别
face = cv2.resize(gray[y:y+h,x:x+w], (200,200))
# 预测人物
params = model.predict(face)
# 写上人物名字
cv2.putText(image,name[params[0]],(x,y-20),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),2)
show(image)