# 数据读取-图像
import cv2
import matplotlib.pyplot as plt
import numpy as np
# %matplotlib inline # jupyter中使用
img = cv2.imread('cat.jpg')
import cv2
img = cv2.imread('cat.jpg')
# 图像的显示,也可以创建多个窗口
cv2.imshow('image', img)
# 等待时间,毫秒级,0表示任意键终止
cv2.waitKey(0)
cv2.destroyAllWindows()
# 显示函数封装
import cv2
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
# 读取灰度图
img = cv2.imread('cat.jpg', cv2.IMREAD_GRAYSCALE)
# 保存图片
cv2.imwrite('mycat.jpg', img)
# np.array的格式
type(img)
img.size # 查看大小
img.dtype # 查看数值类型 uint8
import cv2
vc = cv2.VideoCapture('test.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('result', gray)
if cv2.waitKey(0) & 0xFF == 27:
break
vc.release()
cv2.destroyAllWindows()
import cv2
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('cat.jpg')
# 截取部分图像数据
cat = img[0:200, 0:200]
cv_show('cat', cat)
# 颜色通道提取
b, g, r = cv2.split(img)
# 图像组合
img = cv2.merge((b, g, r))
# 只保留R BGR--->012
cur_img = img.copy()
cur_img[:, :, 0] = 0
cur_img[:, :, 1] = 0
cv_show('R', cur_img)
import cv2
img = cv2.imread('cat.jpg')
# 上下左右填充的大小
top_size, bottom_size, left_size, right_size = (50, 50, 50, 50)
replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_CONSTANT, value=0)
import matplotlib.pyplot as plt
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') # 反射法, 对感兴趣的图像中的像素在两边进行复制,如:fedcba:abcdefgh:hgfedcb
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101') # 反射法, 以最边缘像素为轴,对称, gfedcb|abcdefgh|gfed
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP') # 外包装法, cdefgh|abcdefgh|abcdefg
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT') # 常量法, 常数值填充
plt.show()
import matplotlib.pyplot as plt
import cv2
img_cat = cv2.imread('cat.jpg')
img_dog = cv2.imread('dog.jpg')
img_cat2 = img_cat + 10
img_cat[:5, :, 0] # 打印前五行
img_cat2[:5, :, 0]
# 相当于 %256, 取余数
(img_cat + img_cat2)[:5, :, 0]
cv2.add(img_cat, img_cat2)[:5, :, 0] # 最大值255,相加超过的像素,会得到255
# 图像融合,大小必须一致
img_cat.shape
img_dog = cv2.resize(img_dog, (500, 414))
img_dog.shape
res = cv2.resize(img_cat, (0, 0), fx=3, fy=1)
plt.imshow(res)
res = cv2.resize(img_cat, (0, 0), fx=1, fy=3)
plt.imshow(res)
res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0) # 指定权重后融合
plt.show(res)
import cv2
import numpy as np
img = cv2.imread('dige.png')
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((5, 5), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)
cv2.imread('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
pie = cv2.imread('pie.png')
kernel = np.ones((30, 30), np.uint8)
erosion_1 = cv2.erode(pie, kernel, iterations=1)
erosion_2 = cv2.erode(pie, kernel, iterations=2)
erosion_3 = cv2.erode(pie, kernel, iterations=3)
res = np.hstack((erosion_1, erosion_2, erosion_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
import numpy as np
import cv2
img = cv2.imread('dige.png')
kernel = np.ones((3, 3), np.uint8)
dige_ersion = cv2.erode(img, kernel, iterations=1) # 腐蚀
kernel = np.ones((3, 3), np.uint8)
dige_dilate = cv2.dilate(dige_ersion, kernel, iterations=1) # 膨胀
import cv2
import numpy as np
# 开:先腐蚀,再膨胀
img = cv2.imread('dige.png')
kernel = np.ones((5, 5), np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) # morphology:形态学
cv2.imshow('opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 闭运算:先膨胀,再腐蚀
img = cv2.imread('dige.png')
kernel = np.ones((5, 5), np.uint8)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.imshow('closing', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()
import numpy as np
import cv2
# 梯度=膨胀-腐蚀 (减法运算) 结果会是一个轮廓
pie = cv2.imread('pie.png')
kernel = np.ones((7, 7), np.uint8)
dilate = cv2.dilate(pie, kernel, iterations=5)
erosion = cv2.erode(pie, kernel, iterations=5)
res = np.hstack((dilate, erosion))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)
cv2.imshow('gradient', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
kernel = np.ones((7, 7), np.uint8)
# 礼帽
img = cv2.imread('dige.png')
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv2.imshow('tophat', tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 黑帽
img = cv2.imread('dige.png')
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('blackhat', blackhat)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
img = cv2.imread('pie.png', cv2.IMREAD_GRAYSCALE)
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=0)
cv_show('sobelX', sobelx)
import cv2
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('pie.png', cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=0)
# 取绝对值
sobelx = cv2.convertScaleAbs(sobelx)
cv_show('sobelx', sobelx)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=0)
sobely = cv2.convertScaleAbs(sobely)
cv_show(sobely, 'sobely')
# 分别计算x, y, 再求和
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
cv_show('sobelxy', sobelxy)
# 不建议直接计算
sobelxy = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=0)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show('sobelxy', sobelxy)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EC86pmD0-1667466692507)(image/Scharr算子.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yjA54Bgr-1667466692508)(img.png)]
import numpy as np
import cv2
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 不同算子的差异
img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=0)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=0)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
# 捕捉的会更丰富
scharrx = cv2.Scharr(img, cv2.CV_64F, 1, 0)
scharry = cv2.Scharr(img, cv2.CV_64F, 0, 1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx, 0.5, scharry, 0.5, 0)
laplacian = cv2.Laplacian(img, cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
res = np.stack(sobelxy, scharrxy, laplacian)
cv_show('res', res)
# 简单的平均卷积操作
import cv2
img = cv2.imread('lenaNoise.png')
blur = cv2.blur(img, (3, 3)) # 均值滤波
cv2.imshow('blur', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 方框滤波
# 基本和均值一样,可以选择归一化
box = cv2.boxFilter(img, -1, (3, 3), normalize=True) # 归一化,主要处理越界问题
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()
import numpy as np
import cv2
img = cv2.imread('lenaNoise.png')
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
aussian = cv2.GaussianBlur(img, (5, 5), 1)
cv2.imshow('aussian', aussian)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 中值滤波:从小到大排序,找中间的
median = cv2.medianBlur(img, 5) # 中值滤波
cv2.imshow('median', median)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 展示所有
res = np.stack((aussian, median)) # 横着的
res_v = np.vstack((aussian, median)) # 竖着的
print(res)
cv2.imshow('aussian vs median', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
import matplotlib.pyplot as plt
import cv2
img_gray = cv2.imread('lenaNoise.png', cv2.IMREAD_GRAYSCALE)
ret, thread1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thread2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thread3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thread4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thread5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img_gray, thread1, thread2, thread3, thread4, thread5]
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()
import numpy as np
import cv2
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
v1 = cv2.Canny(img, 80, 150)
v2 = cv2.Canny(img, 5, 100)
res = np.stack((v1, v2))
cv_show('res', res)
cv2.findContours(img, mode, method)
mode: 轮廓检索模式
RETR_EXTERNAL: 只检索最外面的轮廓
RETR_LIST: 检索所有的轮廓,并将其保存到一条链表中
RETR_CCOMP: 检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界
RETR_TREE: 检索所有的轮廓,并重构嵌套轮廓的整个层次
method: 轮廓逼近的方法
CHAIN_APPROX_NONE: 以Freeman链码的方式输出轮廓,所有其他方法输出多边形
CHAIN_APPROX_SIMPLE: 压缩水平的,垂直的和斜的部分,也就是,函数只保留他们的终点部分
import cv2
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show('thresh', thresh)
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
import cv2
# 模板匹配
img = cv2.imread('lena.jpg', 0)
template = cv2.imread('face.jpg', 0)
h, w = template.shape[:2]
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF',
'cv2.TM_SQDIFF_NORMED']
res = cv2.matchTemplate(img, template, 1)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
import cv2
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('AM.png')
cv_show('img', img)
up = cv2.pyrUp(img)
cv_show('up', up)
print(up.shape)
down = cv2.pyrDown(img)
cv_show('down', down)
print(down.shape)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lK9OkKZY-1667466692510)(image/拉普拉斯金字塔.png)]
import cv2
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('car.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
res, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show('thresh', thresh)
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# contours 轮廓信息
# 传入绘制图像,轮廓,轮廓索引,颜色模式, 线条厚度
# 注意需要copy, 要不原图会变...
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2) # -1是指全部的轮廓 2 线条的宽度
cv_show('res', res)
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, 0, (0, 0, 255), 2) # 0 按顺序进行选择
cv_show('res', res)
import numpy as np
import matplotlib.pyplot as plt
import cv2
img = cv2.imread('lena.jpg', 0)
template = cv2.imread('face.jpg', 0)
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF',
'cv2.TM_SQDIFF_NORMED']
w, h = template.shape[:2]
for meth in methods:
img2 = img.copy()
# 匹配方法的真值
method = eval(meth)
print(method)
res = cv2.matchTemplate(img, template, method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# 如果是平方差匹配TM_SQDIFF 或 归一化平方差匹配TM_SQDIFF_NORMED, 取最小值
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
# 画矩形
cv2.rectangle(img2, top_left, bottom_right, 255, 2)
plt.subplot(121), plt.imshow(res, cmap='gray')
plt.xticks([]), plt.yticks([]) # 隐藏坐标轴
plt.subplot(122), plt.imshow(img2, cmap='gray')
plt.xticks([]), plt.yticks([])
plt.suptitle(meth)
plt.show()
# 匹配多个对象
img_rgb = cv2.imread('mario.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('mario_coin.jpg', 0)
h, w = template.shape[:2]
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
# 取匹配程度大于80%的坐标
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
bottom_right = (pt[0] + w, pt[1] + h)
cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
cv2.imshow('img_rgb', img_rgb)
cv2.waitKey(0)
import cv2
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('car.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
res, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show('thresh', thresh)
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# 轮廓特征
cnt = contours[0] # 拿第一轮廓
# 面积
cv2.contourArea(cnt)
# 周长 True表示闭合
cv2.arcLength(cnt, True)
# 轮廓近似
img = cv2.imread('contours2.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]
draw_img = img.copy()
res = cv2.drawContours(draw_img, [cnt], -1, (0, 0, 255), 2)
cv_show('res', res)
epsilon = 0.1 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
draw_img = img.copy()
res = cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2)
cv_show('res', res)
# 边界矩形
cnt = contours[0]
x, y, w, h = cv2.boundingRect(cnt)
img = cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv_show('img', img)
area = cv2.contourArea(cnt)
x, y, w, h = cv2.boundingRect(cnt)
rect_area = w * h
extent = float(area) / rect_area
print("轮廓面积与边界矩形比----", extent)
# 外接圆
(x, y), radius = cv2.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
img = cv2.circle(img, center, radius, (0, 255, 0), 2)
cv_show('img', img)