这是opencv python一些基本语法的简记
1. 基本操作
打开视频、截取部分图片数据、颜色通道提取 #边界填充 #数据计算 #图像融合 #图像阈值
1.1 函数库导入
import cv2
import matplotlib.pyplot as plt
import numpy as np
#简化后续代码
def showimg(name, value):
cv2.imshow(name, value)
cv2.waitKey(0)
cv2.destroyAllWindows()
1.2 基础
#导入图片(文件名,数据类型:cv2.IMREAD_GRAYSCALE)
img = cv2.imread('test.jfif')
img2 = cv2.imread('test.jfif', cv2.IMREAD_GRAYSCALE)
#显示图片 窗口名称 图像
cv2.imshow('image1', img)
cv2.imshow('image2', img2)
#等待
cv2.waitKey(100)
#尺寸
print(img.shape)
print(img2.shape)
#图像保存
print(cv2.imwrite('img_1.png', img))
cv2.imwrite('img_2.png', img2)
#文件类型
type(img)
#像素点数
print(img.size)
#数据类型
print(img.dtype)
#关闭窗口
cv2.destroyAllWindows()
1.3 打开视频
vc = cv2.VideoCapture('vdtest.mp4')
#检查是否打开正确
if vc.isOpened():
open,frame = vc.read()
else:
open = False
#遍历每一帧
while open:
ret, frame = vc.read()
if frame is None:
break
if ret == True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('result1', frame)
if cv2.waitKey(15) & 0xFF == 27 :
break
cv2.imshow('result1', gray)
#0xFF ==27 按退出键退出
if cv2.waitKey(15) & 0xFF == 27 :
break
vc.release()
cv2.destroyAllWindows()
1.4 截取部分图片数据
img = cv2.imread('test.jfif')
part = img[200:1000,0:1000]
cv2.imshow('part', part)
cv2.waitKey(1000)
cv2.destroyAllWindows()
1.5 颜色通道提取
img = cv2.imread('test.jfif')
b, g, r = cv2.split(img)
cv2.imshow('blue', b)
cv2.imshow('green', g)
cv2.imshow('red', r)
img = cv2.merge((r,b,g)) #正常:b,g,r
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
1.6 边界填充
img = cv2.imread('test.jfif')
top_size, bottom_size, left_size, right_size = (200, 200, 200, 200)
#复制边缘像素
replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType = cv2.BORDER_REPLICATE)
#反射 abcd|dcba
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType = cv2.BORDER_REFLECT)
#反射 abcd|cba
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType = cv2.BORDER_REFLECT_101)
#外包装:重复图片
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType = cv2.BORDER_WRAP)
#填充单个像素
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType = cv2.BORDER_CONSTANT, value = 256)
plt.subplot(231), plt.imshow(img, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
1.7 数据计算
img = cv2.imread('test.jfif')
img2 = img + 100
img2_2 = cv2.add(img, 100)
img3 = img + img # 相当于%256
img4 = -img
img5 = img*img
img6 = img*100
showimg('img', img)
showimg('img2', img2)
showimg('img2_2', img2_2)
showimg('img4', img4)
showimg('img5', img5)
showimg('img6', img6)
1.8 图像融合
img = cv2.imread('test.jfif')
img2 = cv2.imread('test2.jfif')
print(img.shape)
print(img2.shape)
showimg('1', img)
showimg('2', img2)
img = cv2.resize(img, (347, 234))
img_2 = cv2.resize(img, (0,0), fx = 2, fy = 2)
showimg('1', img)
showimg('_2', img_2)
imgadd = cv2.addWeighted(img, 0.4, img2, 0.4, 0.2)
showimg('add', imgadd)
1.9 图像阈值
'''
ret, dst = cv2.threshold(src, thresh, maxval, type)
src:原始单通道图像
dst:输出图
thresh:阈值
maxval:像素超过阈值所赋的值
type:二值化类型
'''
img = cv2.imread('test.jfif',cv2.IMREAD_GRAYSCALE)
ret, img1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) #超过取最大值,否则取0
ret, img2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV) #与上相反
ret, img3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC) #超为阈值否则不变
ret, img4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO) #超不变,否则为0
ret, img5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV) #与上相反
titles = ['0', '1', '2', '3', '4', '5']
images = [img, img1, img2, img3, img4, img5]
for i in range(6):
plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
2 滤波
使图像平滑
import cv2
import matplotlib.pyplot as plt
import numpy as np
def showimg(name, value):
cv2.imshow(name, value)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('noisy.png')
img = cv2.resize(img, (0,0), fx = 0.5, fy = 0.5)
showimg('image', img)
#均值滤波(简单的平均卷积)
blur = cv2.blur(img, (5,5))
showimg('blur', blur)
#方框滤波
box = cv2.boxFilter(img, -1, (3,3), normalize = False)
showimg("box", box)
#高斯滤波
aussian = cv2.GaussianBlur(img, (3,3), 1)
showimg("aus", aussian)
#中值滤波
median = cv2.medianBlur(img, 5)
showimg("median", median)
#res = np.vstack((blur, aussian, median))
res = np.hstack((blur, aussian, median))
showimg("all", res)
3 腐蚀膨胀
import cv2
import matplotlib.pyplot as plt
import numpy as np
def showimg(name, value):
cv2.imshow(name, value)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('corrode.jpg')
showimg('1', img)
#设置卷积核
kernel = np.ones((5,5), np.uint8)
#腐蚀
erosion = cv2.erode(img, kernel, iterations = 1)
showimg('correde', erosion)
#膨胀
dige = cv2.dilate(img, kernel, iterations = 1)
showimg('dilate', dige)
#开运算:先腐蚀,再膨胀
open = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
showimg('open', open)
#闭运算:先膨胀,再腐蚀
close = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
showimg('close', close)
#梯度 = 膨胀 - 腐蚀
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
showimg('gradient',gradient)
#礼帽:原始 - 开运算
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
showimg('top', tophat)
#黑帽:闭运算 - 原始
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
showimg('black', blackhat)
4 梯度运算
提取图像边缘
import cv2
import matplotlib.pyplot as plt
import numpy as np
def showimg(name, value):
cv2.imshow(name, value)
cv2.waitKey(0)
cv2.destroyAllWindows()
#Sobel算子:cv2.Sobel(img, ddepth, dx, dy, ksize)
'''
Gx = [-1 0 +1] * A Gy = [-1 -2 -1]
[-2 0 +2] [0 0 0]
[-1 0 +1] [+1 +2 +1]
'''
img = cv2.imread('black.jpg', cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize = 3)
showimg('1x', sobelx)
sobelx = cv2.convertScaleAbs(sobelx)
showimg('sobelx', sobelx)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize = 3)
showimg('1y', sobely)
sobely = cv2.convertScaleAbs(sobely)
showimg('sobely', sobely)
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
showimg('sobelxy', sobelxy)
#scharr算子
'''
Gx = [-3 0 +3] Gy = [-3 -10 +3]
[-10 0 +10] [0 0 0]
[-3 0 +3] [-3 -10 +3]
'''
schx = cv2.Scharr(img, cv2.CV_64F, 1, 0)
schy = cv2.Scharr(img, cv2.CV_64F, 0, 1)
schxy = cv2.addWeighted(schx, 0.5, schy, 0.5, 0)
schxy = cv2.convertScaleAbs(schxy)
showimg('schxy', schxy)
#laplacian算子
'''
G = [0 1 0]
[1 -4 1]
[0 1 0]
'''
lap = cv2.Laplacian(img, cv2.CV_64F)
lap = cv2.convertScaleAbs(lap)
showimg('lap', lap)
5 canny边缘检测
'''
1)高斯滤波 2)计算每个点梯度强度与方向 3)非极大值抑制:消除边缘检测带来杂散效应
4)应用双阈值检测确定真实潜在边缘 5)抑制孤立弱边缘完成检测
'''
#(原图, minvalue, maxvalue)
v1 = cv2.Canny(img, 80, 150)
v2 = cv2.Canny(img, 50, 100)
res = np.hstack((v1, v2))
showimg('Canny', res)
6 图像金字塔
变大变小真奇妙、特征提取
#用途:特征提取等
import cv2
import matplotlib.pyplot as plt
import numpy as np
def showimg(name, value):
cv2.imshow(name, value)
cv2.waitKey(0)
cv2.destroyAllWindows()
#高斯金字塔
'''
1.向下采样法:大变小
1/16 * [1 4 6 4 1]
[4 16 24 16 4]
[6 24 36 24 6]
[4 16 24 16 4]
[1 4 6 4 1]
1)将Gi与高斯核卷积
2)将偶数行和列去除
'''
'''
2.向上采样法:小变大
1)图像在每个方向扩大为原来两倍,新增行列用0填充
2)用先前的高斯核卷积
'''
img = cv2.imread('test2.jfif')
showimg('origin', img)
up = cv2.pyrUp(img)
showimg('up', up)
down = cv2.pyrDown(up)
showimg('down', down)
v1 = cv2.Canny(img, 80, 150)
v2 = cv2.Canny(down, 80, 150)
res = np.hstack((v1, v2))
showimg('Canny', res)
#拉普拉斯金字塔
#Li = Gi - pyrUp(pyrDown(Gi))
down2 = cv2.pyrDown(img)
up2 = cv2.pyrUp(down2)
print(up2.shape)
img = cv2.copyMakeBorder(img, 0, 0, 1, 0, borderType = cv2.BORDER_REPLICATE)
print('原图', img.shape)
lap = img - up2
showimg('lap', lap)
7 图像轮廓
import cv2
import matplotlib.pyplot as plt
import numpy as np
def showimg(name, value):
cv2.imshow(name, value)
cv2.waitKey(0)
cv2.destroyAllWindows()
'''
cv2.findContours(img, mode, method)
mode:轮廓检测模式
RETR_EXTERNAL 只检测最外面轮廓
RETR_LIST 检测所有轮廓,并保存到链表
RETR_CCOMP 检测所有.分为两层,顶层是各部分外部边界,第二层是空洞边界
RETR_TREE 检测所有轮廓,并重构嵌套轮廓的整个层次
method:轮廓逼近方法
CHAIN_APPROX_NONE 以freeman链码的方式输出轮廓,所有其他方法输出多边形
CHAIN_APPROX_SIMPLE 压缩水平的,垂直的,斜的部分,只保留终点部分
'''
img = cv2.imread('apple.png')
white = cv2.imread('white.jfif')
l11, l12, l13 = img.shape
white = cv2.resize(white, (l12, l11))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]
showimg('thresh', thresh)
img2 = img.copy()
#(img, 轮廓contours, 第几个轮廓-1, 线颜色(0,0,255), 线宽2)
res = cv2.drawContours(white, contours, -1, (0,0,255), 2)
showimg('res', res)
#轮廓近似
epsilon = 0.1*cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
img3 = img.copy()
res = cv2.drawContours(img3, [approx], -1, (0,0,255), 2)
showimg('res', res)