demo代码:https://github.com/2012Netsky/opencv
前言
和Python一样,当前的OpenCV也有两个大版本,OpenCV2和OpenCV3。相比OpenCV2,OpenCV3提供了更强的功能和更多方便的特性。 根据功能和需求的不同,OpenCV中的函数接口大体可以分为如下部分:
-
core:核心模块,主要包含了OpenCV中最基本的结构(矩阵,点线和形状等),以及相关的基础运算/操作。 -
imgproc:图像处理模块,包含和图像相关的基础功能(滤波,梯度,改变大小等),以及一些衍生的高级功能(图像分割,直方图,形态分析和边缘/直线提取等)。 -
highgui:提供了用户界面和文件读取的基本函数,比如图像显示窗口的生成和控制,图像/视频文件的IO等。 -
如果不考虑视频应用,以上三个就是最核心和常用的模块了。针对视频和一些特别的视觉应用,OpenCV也提供了强劲的支持: -
video:用于视频分析的常用功能,比如光流法(Optical Flow)和目标跟踪等。 -
calib3d:三维重建,立体视觉和相机标定等的相关功能。 -
features2d:二维特征相关的功能,主要是一些不受专利保护的,商业友好的特征点检测和匹配等功能,比如ORB特征。 -
object:目标检测模块,包含级联分类和Latent SVM -
ml:机器学习算法模块,包含一些视觉中最常用的传统机器学习算法。 -
flann:最近邻算法库,Fast Library for Approximate -
Nearest Neighbors,用于在多维空间进行聚类和检索,经常和关键点匹配搭配使用。 -
gpu:包含了一些gpu加速的接口,底层的加速是CUDA实现。 -
photo:计算摄像学(Computational Photography)相关的接口,当然这只是个名字,其实只有图像修复和降噪而已。 -
stitching:图像拼接模块,有了它可以自己生成全景照片。 -
nonfree:受到专利保护的一些算法,其实就是SIFT和SURF。 -
contrib:一些实验性质的算法,考虑在未来版本中加入的。 -
legacy:字面是遗产,意思就是废弃的一些接口,保留是考虑到向下兼容。 -
ocl:利用OpenCL并行加速的一些接口。 -
superres:超分辨率模块,其实就是BTV-L1(Biliteral Total Variation – L1regularization)算法 -
viz:基础的3D渲染模块,其实底层就是著名的3D工具包VTK(Visualization Toolkit)。
从使用的角度来看,和OpenCV2相比,OpenCV3的主要变化是更多的功能和更细化的模块划分。
python——opencv基础 图像的表示 已知单通道的灰度图像在计算机中的表示是一个8位无符号整形的矩阵,在oncv的C++代码中,表示图像有专门的结构cv::Mat,但python中有numpy这种强大的基础工具,所以该矩阵就用numpy的array表示,多通道就是红绿蓝(RGB)三通道。
1、OpenCV读图及显示
import cv2
img = cv2.imread("psc.jpg")
cv2.namedWindow("Image")
cv2.imshow("Image", img)
cv2.waitKey(-1)
cv2.destroyAllWindows()
2、自定义函数读图及显示
def show_picture(picture):
import cv2
img = cv2.imread(picture)
print(type(img), img.size, img.shape, img.dtype)
show_picture('psc.jpg')
3、读取摄像头图片
import cv2 as cv
def video_demo():
capture = cv.VideoCapture(0)
while (True):
ref, frame = capture.read()
cv.imshow("1", frame)
c = cv.waitKey(10)
if c == 27:
capture.release()
break
video_demo()
cv.waitKey()
cv.destroyAllWindows()
4、裁剪
import cv2
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('psc.jpg')
cat = img[0:50, 0:200]
cv_show('cat', cat)
5、通道分离及通道融合
import cv2
img = cv2.imread('psc.jpg')
print(img.shape)
b, g, r = cv2.split(img)
print(r.shape, g.shape, b.shape)
img = cv2.merge((r, g, b))
print(img.shape)
cv2.imwrite('mycat.png', img)
cur_img = img.copy()
cur_img[:, :, 0] = 0
cur_img[:, :, 1] = 0
cv_show('R', cur_img)
cur_img = img.copy()
cur_img[:, :, 0] = 0
cur_img[:, :, 2] = 0
cv_show('G', cur_img)
cur_img = img.copy()
cur_img[:, :, 1] = 0
cur_img[:, :, 2] = 0
cv_show('B', cur_img)
6、边界填充
'''
BORDER_REPLICATE:复制法,也就是复制最边缘像素。
BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb
BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba
BORDER_WRAP:外包装法cdefgh|abcdefgh|abcdefg
BORDER_CONSTANT:常量法,常数值填充。
'''
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')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')
plt.show()
7、数值计算
import cv2
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img_cat = cv2.imread('cat.jpg')
img_dog = cv2.imread('dog.jpg')
rows, cols = img_cat.shape[:2]
img_dog = cv2.resize(img_dog, (cols, rows), interpolation=cv2.INTER_CUBIC)
8、第二种显示图片方式
import matplotlib.pyplot as plt
plt.subplot(121), plt.imshow(img_cat), plt.title('ORIGINAL')
plt.subplot(122), plt.imshow(img_dog), plt.title('ORIGINAL')
plt.show()
cv2.imshow('cat', img_cat)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imshow('dog', img_dog)
cv2.waitKey(0)
cv2.destroyAllWindows()
img_cat2 = img_cat + 10
print(img_cat[:5, :, 0], img_cat2[:5, :, 0], (img_cat + img_cat2)[:5, :, 0], cv2.add(img_cat, img_cat2)[:5, :, 0])
9、图像融合(高级)
import cv2
img_cat = cv2.imread('cat.jpg')
img_dog = cv2.imread('dog.jpg')
rows, cols = img_cat.shape[:2]
img_dog = cv2.resize(img_dog, (cols, rows))
print(img_cat.shape, img_dog.shape)
print(img_cat + img_dog)
res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0)
print(res.shape)
import matplotlib.pyplot as plt
plt.subplot(131), plt.imshow(img_cat), plt.title('ORIGINAL1')
plt.subplot(132), plt.imshow(img_dog), plt.title('ORIGINAL2')
plt.subplot(133), plt.imshow(res), plt.title('ORIGINAL3')
plt.imshow(res)
10、调整大小
import cv2
import matplotlib.pyplot as plt
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('psc.jpg')
res = cv2.resize(img, (0, 0), fx=4, fy=4)
print(img.shape, res.shape)
11、matplotlib 显示图像
from PIL import Image
import matplotlib.pyplot as plt
img = Image.open('psc.jpg')
print('1', img)
print('2', img)
plt.figure("Image")
print('3')
plt.imshow(img)
print('4')
plt.axis('on')
plt.title('image')
print('5')
plt.show()
12、显示多张图片
from PIL import Image
import matplotlib.pyplot as plt
img = Image.open('psc.jpg')
gray = img.convert('L')
r, g, b = img.split()
img_merged = Image.merge('RGB', (r, g, b))
plt.figure(figsize=(10, 5))
plt.suptitle('Multi_Image')
plt.subplot(2, 3, 1), plt.title('image')
plt.imshow(img), plt.axis('off')
plt.subplot(2, 3, 2), plt.title('gray')
plt.imshow(gray, cmap='gray'), plt.axis('off')
plt.subplot(2, 3, 3), plt.title('img_merged')
plt.imshow(img_merged), plt.axis('off')
plt.subplot(2, 3, 4), plt.title('r')
plt.imshow(r, cmap='gray'), plt.axis('off')
plt.subplot(2, 3, 5), plt.title('g')
plt.imshow(g, cmap='gray'), plt.axis('off')
plt.subplot(2, 3, 6), plt.title('b')
plt.imshow(b, cmap='gray'), plt.axis('off')
plt.show()
13、灰度图
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('psc.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print(img_gray.shape)
cv2.imshow("img_gray", img_gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
cv2.imshow("hsv", hsv)
cv2.waitKey(0)
cv2.destroyAllWindows()
14、阈值分割
'''
ret, dst = cv2.threshold(src, thresh, maxval, type)
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
thresh: 阈值
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
type: 二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV
cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
cv2.THRESH_BINARY_INV THRESH_BINARY的反转
cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变
cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0
cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转
'''
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, 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()
15、显示图片
img = cv2.imread('cat.jpg')
cv2.namedWindow("Image")
cv2.imshow('Image', img)
cv2.waitKey(-1)
cv2.destroyAllWindows()
16、显示
import cv2
img = cv2.imread("psc.jpg")
cv2.imshow("Image", img)
cv2.waitKey(-1)
cv2.destroyAllWindows()
17、滤波
img = cv2.imread('cat.jpg')
blur = cv2.blur(img, (3, 3))
cv2.imshow('blur', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('cat.jpg')
box = cv2.boxFilter(img, -1, (3, 3), normalize=True)
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('cat.jpg')
box = cv2.boxFilter(img, -1, (3, 3), normalize=False)
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('cat.jpg')
aussian = cv2.GaussianBlur(img, (5, 5), 1)
cv2.imshow('aussian', aussian)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('cat.jpg')
median = cv2.medianBlur(img, 5)
cv2.imshow('median', median)
cv2.waitKey(0)
cv2.destroyAllWindows()
res = np.hstack((blur, aussian, median))
cv2.imshow('median vs average', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
18、形态学-腐蚀操作
import numpy as np
img = cv2.imread('cat.jpg')
kernel = np.ones((3, 3), np.uint8)
print(kernel)
erosion = cv2.erode(img, kernel, iterations=1)
import matplotlib.pyplot as plt
plt.subplot(121), plt.imshow(img), plt.title('img')
plt.subplot(122), plt.imshow(erosion), plt.title('erosion')
plt.show()
pie = cv2.imread('pie.png')
cv2.imshow('pie', pie)
cv2.waitKey(0)
cv2.destroyAllWindows()
19、腐蚀
import numpy as np
img = cv2.imread('cat.jpg')
kernel = np.ones((3, 3), np.uint8)
erosion_1 = cv2.erode(img, kernel, iterations=1)
erosion_2 = cv2.erode(img, kernel, iterations=2)
erosion_3 = cv2.erode(img, kernel, iterations=3)
res = np.hstack((erosion_1, erosion_2, erosion_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
20、形态学-膨胀操作
import numpy as np
img = cv2.imread('cat.jpg')
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((3, 3), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)
kernel = np.ones((3, 3), np.uint8)
dilate = cv2.dilate(erosion, kernel, iterations=1)
res = np.hstack((img, erosion, dilate))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
21、腐蚀
import numpy as np
img = cv2.imread('cat.jpg')
kernel = np.ones((30, 30), np.uint8)
dilate_1 = cv2.dilate(img, kernel, iterations=1)
dilate_2 = cv2.dilate(img, kernel, iterations=2)
dilate_3 = cv2.dilate(img, kernel, iterations=3)
res = np.hstack((dilate_1, dilate_2, dilate_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
22、开运算与闭运算
import numpy as np
img = cv2.imread('cat.jpg')
kernel = np.ones((5, 5), np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv2.imshow('opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('cat.jpg')
kernel = np.ones((5, 5), np.uint8)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.imshow('closing', closing)
cv2.waitKey(0)
cv2.destroyAllWindows()
23、梯度运算
import numpy as np
pie = cv2.imread('cat.jpg')
kernel = np.ones((3, 3), 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', gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()
24、礼帽与黑帽
'''
礼帽 = 原始输入-开运算结果
黑帽 = 闭运算-原始输入
'''
import numpy as np
img = cv2.imread('cat.jpg')
kernel = np.ones((3, 3), np.uint8)
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv2.imshow('tophat', tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('cat.jpg')
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('blackhat ', blackhat)
cv2.waitKey(0)
cv2.destroyAllWindows()
25、图像梯度-Sobel算子
img = cv2.imread('cat.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
'''
dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
ddepth:图像的深度
dx和dy分别表示水平和竖直方向
ksize是Sobel算子的大小
'''
def cv_show(img, name):
cv2.imshow(name, img)
cv2.waitKey()
cv2.destroyAllWindows()
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
cv_show(sobelx, 'sobelx')
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)
cv_show(sobely, 'sobely')
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
cv_show(sobelxy, 'sobelxy')
sobelxy = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show(sobelxy, 'sobelxy')
def cv_show(img, name):
cv2.imshow(name, img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread('cat.jpg', cv2.IMREAD_GRAYSCALE)
cv_show(img, 'img')
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
cv_show(sobelxy, 'sobelxy')
26、图像梯度
'''
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3) sobelxy = cv2.convertScaleAbs(sobelxy) cv_show(sobelxy,'sobelxy')
'''
import numpy as np
def cv_show(img, name):
cv2.imshow(name, img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
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.hstack((sobelxy, scharrxy, laplacian))
cv_show(res, 'res')
27、Canny边缘检测
'''
Canny边缘检测
1) 使用高斯滤波器,以平滑图像,滤除噪声。
2) 计算图像中每个像素点的梯度强度和方向。
3) 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
4) 应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
5) 通过抑制孤立的弱边缘最终完成边缘检测。
'''
import numpy as np
img = cv2.imread("cat.jpg", cv2.IMREAD_GRAYSCALE)
def cv_show(img, name):
cv2.imshow(name, img)
cv2.waitKey()
cv2.destroyAllWindows()
v1 = cv2.Canny(img, 80, 150)
v2 = cv2.Canny(img, 50, 100)
res = np.hstack((v1, v2))
cv_show(res, 'res')
img = cv2.imread("car.png", cv2.IMREAD_GRAYSCALE)
v1 = cv2.Canny(img, 120, 250)
v2 = cv2.Canny(img, 50, 100)
res = np.hstack((v1, v2))
cv_show(res, 'res')
28、图像金字塔
'''
图像金字塔
高斯金字塔
拉普拉斯金字
'''
import numpy as np
def cv_show(img, name):
cv2.imshow(name, img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread("cat.jpg")
cv_show(img, 'img')
print('1', img.shape)
up = cv2.pyrUp(img)
cv_show(up, 'up')
print('2', up.shape)
down = cv2.pyrDown(img)
cv_show(down, 'down')
print('3', down.shape)
up2 = cv2.pyrUp(up)
cv_show(up2, 'up2')
print('4', up2.shape)
up = cv2.pyrUp(img)
up_down = cv2.pyrDown(up)
cv_show(up_down, 'up_down')
cv_show(np.hstack((img, up_down)), 'up_down')
up = cv2.pyrUp(img)
up_down = cv2.pyrDown(up)
cv_show(img - up_down, 'img-up_down')
29、拉普拉斯金字塔
def cv_show(img, name):
cv2.imshow(name, img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread("cat.jpg")
down = cv2.pyrDown(img)
down_up = cv2.pyrUp(down)
l_1 = img - down_up
cv_show(l_1, 'l_1')
30、图像轮廓
'''
图像轮廓
cv2.findContours(img,mode,method)
mode:轮廓检索模式
RETR_EXTERNAL :只检索最外面的轮廓;
RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中;
RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次;
method:轮廓逼近方法
CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。
'''
def cv_show(img, name):
cv2.imshow(name, img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread('cat.jpg')
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)
cv_show(img, 'img')
31、传入绘制图像
def cv_show(img, name):
cv2.imshow(name, img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread('cat.jpg')
draw_img = img.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
cv_show(res, 'res')
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, 0, (0, 0, 255), 2)
cv_show(res, 'res')
cnt = contours[0]
cv2.contourArea(cnt)
cv2.arcLength(cnt, True)
img = cv2.imread('contours2.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
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.15 * 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')
32、边界矩形
img = cv2.imread('contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
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')
33、傅里叶变换
'''
傅里叶变换
我们生活在时间的世界中,早上7:00起来吃早饭,8:00去挤地铁,9:00开始上班。。。以时间为参照就是时域分析。
但是在频域中一切都是静止的!
https://zhuanlan.zhihu.com/p/19763358
傅里叶变换的作用
高频:变化剧烈的灰度分量,例如边界
低频:变化缓慢的灰度分量,例如一片大海
波
低通滤波器:只保留低频,会使得图像模糊
高通滤波器:只保留高频,会使得图像细节增强
opencv中主要就是cv2.dft()和cv2.idft(),输入图像需要先转换成np.float32 格式。
得到的结果中频率为0的部分会在左上角,通常要转换到中心位置,可以通过shift变换来实现。
cv2.dft()返回的结果是双通道的(实部,虚部),通常还需要转换成图像格式才能展示(0,255)。
'''
34、得到灰度图能表示的形式
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('lena.jpg', 0)
img_float32 = np.float32(img)
dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
35、低通滤波
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('lena.jpg', 0)
img_float32 = np.float32(img)
dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2)
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 1
fshift = dft_shift * mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img_back, cmap='gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])
plt.show()
36、高通滤波
img = cv2.imread('lena.jpg', 0)
img_float32 = np.float32(img)
dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2)
mask = np.ones((rows, cols, 2), np.uint8)
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 0
fshift = dft_shift * mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img_back, cmap='gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])
plt.show()
37、直方图与模板匹配
import cv2
import numpy as np
import matplotlib.pyplot as plt
def cv_show(img, name):
cv2.imshow(name, img)
cv2.waitKey()
cv2.destroyAllWindows()
38、直方图
'''
v2.calcHist(images,channels,mask,histSize,ranges)
images: 原图像图像格式为 uint8 或 ?oat32。当传入函数时应 用中括号 [] 括来例如[img]
channels: 同样用中括号括来它会告函数我们统幅图 像的直方图。如果入图像是灰度图它的值就是 [0]如果是彩色图像 的传入的参数可以是 [0][1][2] 它们分别对应着 BGR。
mask: 掩模图像。统整幅图像的直方图就把它为 None。但是如 果你想统图像某一分的直方图的你就制作一个掩模图像并 使用它。
histSize:BIN 的数目。也应用中括号括来
ranges: 像素值范围常为 [0256]
'''
img = cv2.imread('cat.jpg', 0)
hist = cv2.calcHist([img], [0], None, [256], [0, 256])
print(hist.shape)
plt.hist(img.ravel(), 256)
plt.show()
img = cv2.imread('cat.jpg')
color = ('b', 'g', 'r')
for i, col in enumerate(color):
histr = cv2.calcHist([img], [i], None, [256], [0, 256])
plt.plot(histr, color=col)
plt.xlim([0, 256])
39、mask操作
mask = np.zeros(img.shape[:2], np.uint8)
print(mask.shape)
mask[100:300, 100:400] = 255
cv_show(mask, 'mask')
img = cv2.imread('cat.jpg', 0)
cv_show(img, 'img')
masked_img = cv2.bitwise_and(img, img, mask=mask)
cv_show(masked_img, 'masked_img')
hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])
plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask, 'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0, 256])
plt.show()
40、直方图均衡化
img = cv2.imread('clahe.jpg', 0)
plt.hist(img.ravel(), 256);
plt.show()
equ = cv2.equalizeHist(img)
plt.hist(equ.ravel(), 256)
plt.show()
res = np.hstack((img, equ))
cv_show(res, 'res')
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
res_clahe = clahe.apply(img)
res = np.hstack((img, equ, res_clahe))
cv_show(res, 'res')
41、模板匹配
'''
模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度,
这个差别程度的计算方法在opencv里有6种,然后将每次计算的结果放入一个矩阵里,作为结果输出。假如原图
形是AxB大小,而模板是axb大小,则输出结果的矩阵是(A-a+1)x(B-b+1)
'''
img = cv2.imread('lena.jpg', 0)
template = cv2.imread('face.jpg', 0)
h, w = template.shape[:2]
print(img.shape, template.shape)
'''
TM_SQDIFF:计算平方不同,计算出来的值越小,越相关
TM_CCORR:计算相关性,计算出来的值越大,越相关
TM_CCOEFF:计算相关系数,计算出来的值越大,越相关
TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关
TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关
TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1,越相关
公式:https://docs.opencv.org/3.3.1/df/dfb/group__imgproc__object.html#ga3a7850640f1fe1f58fe91a2d7583695d
'''
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, cv2.TM_SQDIFF)
print(res.shape)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
print(min_val, max_val, min_loc, max_loc)
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)
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()
42、匹配多个对象
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
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)
|