使用Python操作opencv的实例代码(所用图片素材地址自行替换)
最后两个例子是利用opencv进行轮廓检测和相似度匹配检测,可以达到实时跟踪画面中的物体
"""
opencv实例
"""
import cv2 # opencv读取的是BGR格式
import matplotlib.pyplot as plt
import numpy as np
# 读取图片,保存图片
def cv_test01():
img1 = cv2.imread('./images/1.jpg', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
print(img1)
print(img1.shape) # 图像的形状
img2 = cv2.imread('./images/1.jpg', cv2.IMREAD_GRAYSCALE) # 读取灰度图片
print(img2.shape)
cv2.imwrite('./images/1_hui.png', img2) # 保存图片
# 显示图像
cv2.imshow('image1', img1) # 将图片显示在窗口
cv2.imshow('image2', img2) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# 读取视频保存视频
def cv_test02():
cap2 = cv2.VideoCapture('./images/1.mp4') # 读取文件
cap = cv2.VideoCapture(0) # 读取摄像头图像
# 定义编解码器并创建VideoWriter对象,用于保存图像
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('./images/output.avi', fourcc, 20.0, (640, 480))
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
# 逐帧捕获
ret, frame = cap.read()
# 如果正确读取帧,ret为True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# 我们在框架上的操作到这里
out.write(frame) # 保存图像
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 读取为灰度图像
# 显示结果帧数
cv2.imshow('frame', gray)
if cv2.waitKey(100) == ord('q'): # 里面的数字表示等待多长时间
break
# 完成所有操作后,释放捕获器
cap.release()
cv2.destroyAllWindows()
# 图像分割
def cv_test03():
img1 = cv2.imread('./images/1.jpg', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
print(img1.shape)
# 图片裁剪
img2 = img1[20:img1.shape[0]-20, 20:img1.shape[1]-20]
print(img2.shape)
# 显示图像
cv2.imshow('image1', img1) # 将图片显示在窗口
cv2.imshow('image2', img2) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# 图像通道读取
def cv_test04():
img1 = cv2.imread('./images/1.jpg', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
b, g, r = cv2.split(img1) # 分别读出每个通道的数据
print(b.shape)
print(g.shape)
print(r.shape)
img2 = cv2.merge((b, g, r))
print(img2.shape)
img3 = img2.copy()
img3[:, :, 0] = 0 # 将蓝色通道变成0
img3[:, :, 1] = 0 # 将绿色通道变成0
print(img3)
cv2.imshow('image3', img3) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# 为图像设置边框(填充)
def cv_test05():
img1 = cv2.imread('./images/1.jpg', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
# 定义上下填充宽度
top_size, bottom_size, left_size, right_size = [50, 50, 50, 50]
img2 = cv2.copyMakeBorder(img1, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
img3 = cv2.copyMakeBorder(img1, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_CONSTANT, value=0)
img4 = cv2.copyMakeBorder(img1, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REFLECT)
img5 = cv2.copyMakeBorder(img1, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REFLECT_101)
img6 = cv2.copyMakeBorder(img1, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_WRAP)
plt.subplot(231), plt.imshow(img1, 'gray'), plt.title('1')
plt.subplot(232), plt.imshow(img2, 'gray'), plt.title('2')
plt.subplot(233), plt.imshow(img3, 'gray'), plt.title('3')
plt.subplot(234), plt.imshow(img4, 'gray'), plt.title('4')
plt.subplot(235), plt.imshow(img5, 'gray'), plt.title('5')
plt.subplot(236), plt.imshow(img6, 'gray'), plt.title('6')
plt.show()
# 图像的基本计算
def cv_test06():
img1 = cv2.imread('./images/1.jpg', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
print(img1[0:5, 0:5, 0])
img2 = img1 + 10 # 加常数
print(img2[0:5, 0:5, 0])
img3 = img2 + img1 # 两个相同大小的图片相加,大于255取超出的部分
print(img3[0:5, 0:5, 0])
img4 = cv2.add(img1, img2) # 两个相同大小的图片相加,大于256取255
print(img4[0:5, 0:5, 0])
# 图像融合
def cv_test07():
img1 = cv2.imread('./images/1.jpg', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
img2 = cv2.imread('./images/2.jpg', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
print(img1.shape)
print(img2.shape)
# 图像变化
img3 = cv2.resize(img2, (192, 108)) # 指定具体数值变化
print(img3.shape)
img4 = cv2.resize(img2, (0, 0), fx=1, fy=3) # 指定比例变化
print(img4.shape)
# 图像融合
img5 = cv2.addWeighted(img1, 0.4, img3, 0.6, 0)
cv2.imshow('image4', img5) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# 腐蚀操作,用于去除毛刺,但是会使得线条变窄,可以再使用膨胀操作,使主要的图像变大。
# 不做演示需要的时候再去查看
# 开运算:先进行腐蚀,再进行膨胀 两个步骤合在一起
# 闭运算:先进行膨胀,再进行腐蚀 两个步骤合在一起
# 梯度运算
def cv_test08():
img1 = cv2.imread('./images/yuan.png', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
kernel = np.ones((3, 3), np.uint8) # 全1矩阵
dilate = cv2.dilate(img1, kernel, iterations=5)
erosion = cv2.erode(img1, kernel, iterations=5)
print(dilate.shape)
print(erosion.shape)
res = np.hstack((dilate, erosion))
print(res.shape)
# 梯度运算函数,用于获取物体边界
gradient = cv2.morphologyEx(img1, cv2.MORPH_GRADIENT, kernel)
cv2.imshow('image5', gradient) # 将图片显示在窗口
cv2.imshow('image4', res) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# 礼帽和黑帽
def cv_test09():
img1 = cv2.imread('./images/yuan2.png', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
kernel = np.ones((5, 5), np.uint8) # 全1矩阵
gradient = cv2.morphologyEx(img1, cv2.MORPH_TOPHAT, kernel)
blackhat = cv2.morphologyEx(img1, cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('gradient', gradient) # 将图片显示在窗口
cv2.imshow('blackhat', blackhat) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# Sobel算子,用于寻找梯度,找边界,复杂图像也可以(重要)
# Gx = [[-1, 0, 1], [-3, 0, 3], [-1, 0, 1]]
def cv_test10():
img1 = cv2.imread('./images/yuan.png', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
sobel = cv2.Sobel(img1, cv2.CV_64F, 1, 0, ksize=3) # ksize=5卷积核大小,1,0只算水平方向,0,1只算竖直方向
sobelx = cv2.convertScaleAbs(sobel) # 取绝对值,不然一边会消失
sobel = cv2.Sobel(img1, cv2.CV_64F, 0, 1, ksize=3) # ksize=5卷积核大小,1,0只算水平方向,0,1只算竖直方向
sobely = cv2.convertScaleAbs(sobel) # 取绝对值,不然一边会消失
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0) # 将竖直方向和水平方向进行叠加,直接用1,1效果不好
cv2.imshow('blackhat', sobelxy) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# Scharr算子 更敏感
# Gx = [-3, 0, 3], [-10, 0, 10], [-3, 0, 3]]
# laplacian算子, 更不敏感
# G = [[0, 1, 0], [1, -4, 1], [0, 1, 0]]
# 图像的平滑处理(卷积)(已经不能使用)
def cv_test11():
img1 = cv2.imread('./images/2.jpg', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
# 均值滤波
blur = cv2.blur(img1, (3, 3))
cv2.imshow('blackhat', blur) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# 高斯与中值滤波 (已经不能使用)
def cv_test12():
img1 = cv2.imread('./images/2.jpg', cv2.IMREAD_COLOR) # 读取彩色图片,默认就是
#aussian = cv2.GaussianBlur(img1, (5, 5), 0) #高斯滤波 报错
medim = cv2.medianBlur(img1, 5)
cv2.imshow('blackhat', medim) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# 阈值操作(重要)
def cv_test13():
img1 = cv2.imread('./images/2.jpg', cv2.IMREAD_GRAYSCALE) # 读取彩色图片,默认就是
ret, thresh1 = cv2.threshold(img1, 127, 255, cv2.THRESH_BINARY) # 彩色图像会对三个通道分别处理再叠加,灰度图像
ret, thresh2 = cv2.threshold(img1, 127, 255, cv2.THRESH_BINARY_INV) # 对上面的图像进行反转
ret, thresh3 = cv2.threshold(img1, 127, 255, cv2.THRESH_TRUNC) # 最大值只能到127,小于不变
ret, thresh4 = cv2.threshold(img1, 127, 255, cv2.THRESH_TOZERO) # 大于127的不变,小于127的全为0
ret, thresh5 = cv2.threshold(img1, 127, 255, cv2.THRESH_TOZERO_INV) # 跟上面哪一个相反
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img1, thresh1, thresh2, thresh3, thresh4, thresh5]
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()
# Canny边缘检测(重要)
# 1.滤波,高斯滤波器
# 2.计算每个像素点的梯度强度和方向
# 3.应用非极大值抑制,,以消除除边沿检测带来的杂散响应。
# 4.应用双阀值检测来确定真实和潜在的边缘
# 5.通过抑制孤立的弱边缘最终完成边缘检测
def cv_test14():
img1 = cv2.imread('./images/canny.jpg', cv2.IMREAD_GRAYSCALE) # 读取彩色图片,默认就是
#b, g, r = cv2.split(img1) # 分别读出每个通道的数据
#print(b)
edges = cv2.Canny(img1, 50, 200)
plt.subplot(121), plt.imshow(img1, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(edges, cmap='gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()
# 轮廓检测
def cv_test15():
img1 = cv2.imread('./images/canny.jpg')
gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) # 读取为灰度图像
# 二值化处理
ret, thresh1 = cv2.threshold(gray, 175, 255, cv2.THRESH_BINARY)
# 提取轮廓
contours, hierarchy = cv2.findContours(thresh1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
img2 = img1.copy()
res = cv2.drawContours(img2, contours, 27, (0, 0, 255), 5)
# 展示图像
cv2.imshow('blackhat', res) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# 轮扣近似,找出最大轮廓进行显示
def cv_test16():
img1 = cv2.imread('./images/canny.jpg')
gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) # 读取为灰度图像
# 二值化处理
ret, thresh1 = cv2.threshold(gray, 175, 255, cv2.THRESH_BINARY)
# 提取轮廓
contours, hierarchy = cv2.findContours(thresh1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# i = 0
# for cnt in contours: # epsilon = 0.001*cv2.arcLength(cnt, True) # approx = cv2.approxPolyDP(cnt, epsilon, True) # # img2 = img1.copy() # res = cv2.drawContours(img2, [approx], -1, (0, 0, 255), 4) # # cv2.imshow('blackhat', res) # 将图片显示在窗口
# cv2.waitKey(0) # 按任意建退出
# cv2.destroyAllWindows()
# print(i) # i = i + 1
# 循环计算每一个轮廓的面积,选出最大的进行显示
area = [0] * len(contours)
i = 0
for cnt in contours:
area[i] = cv2.contourArea(cnt)
i = i + 1
a = area.index(max(area)) # 找出列表中最大值的位置
# 近似处理(前面乘的数越大,轮廓近似越多)
epsilon = 0.004*cv2.arcLength(contours[a], True)
approx = cv2.approxPolyDP(contours[a], epsilon, True)
# 绘制轮廓
img2 = img1.copy()
res = cv2.drawContours(img2, [approx], -1, (0, 0, 255), 2)
# 绘制矩形外轮廓
x, y, w, h = cv2.boundingRect(contours[27])
ju_xing = cv2.rectangle(res, (x, y), (x+w, y+h), (0, 255, 0), 2)
# 展示图像
cv2.imshow('blackhat', ju_xing) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# 相似度匹配(和上面轮廓查找的效果类似),也可以进行多模板匹配
def cv_test17():
img1 = cv2.imread('./images/canny.jpg')
img2 = cv2.imread('./images/canny_mu.jpg')
# 获取图像的宽和高
h, w = img2.shape[:2]
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) # 读取为灰度图像
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) # 读取为灰度图像
# 相似匹配
# 列表中所有的6种比较方法
methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR',
'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']
res = cv2.matchTemplate(gray1, gray2, cv2.TM_SQDIFF_NORMED)
print(res.shape)
# 获取最匹配的位置信息
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# 绘制矩形
img3 = img1.copy()
ju_xing = cv2.rectangle(img3, min_loc, (min_loc[0]+w, min_loc[1]+h), (0, 255, 0), 2)
# 展示图像
cv2.imshow('blackhat', ju_xing) # 将图片显示在窗口
cv2.waitKey(0) # 按任意建退出
cv2.destroyAllWindows()
# 按间距中的绿色按钮以运行脚本。
if __name__ == '__main__':
cv_test17()