智能信息处理
智能信息处理
一、 基础图像识别(OpenCV)
OpenCV(开源计算机视觉库)是一个开源的BSD许可库,其中包含数百种计算机视觉算法。本节课主要介绍OpenCV 2.x API,它本质上是一个C ++ API,与基于C的OpenCV 1.x API相反。
1. OpenCV特点
2. OpenCV下载安装
# 安装numpy库
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装opencv库
pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple
#下载完成后输入以下Python代码检查
import cv2
print(cv2.__version__)
3. 基础学习
-
读取图片、视频、调用外部摄像头
# ========read============ img = cv2.imread("./lena.png") # 读取照片 # DISPLAY cv2.imshow("Lena", img) # 展示照片 cv2.waitKey(0) # 阻挡显示 # =====read video import cv2 frameWidth = 640 # 显示长 frameHeight = 480 # 显示宽 cap = cv2.VideoCapture("./test_video.mp4") # VideoCapture()中参数是0,表示打开笔记本的内置摄像头, # 参数是视频文件路径则打开视频,如vc = cv2.VideoCapture("../testi.mp4") while True: success, img = cap.read() # vc.read()按帧读取视频,success,img是获cap.read()方法的两个返回值。其中success是布尔值, # 如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False。img就是每一帧的图像,是个三维矩阵。 img = cv2.resize(img, (frameWidth, frameHeight)) # 重新设置大小 cv2.imshow("Result", img) # 若没有按下q键,则每1毫秒显示一帧 if cv2.waitKey(1) & 0xFF == ord('q'): break # ===========read webcam================== import cv2 # 假如摄像流为 cap, 那么设置参数是cap.set(参数编号,参数) frameWidth = 640 frameHeight = 480 cap = cv2.VideoCapture(0) # 读取摄像头 cap.set(3, frameWidth) cap.set(4, frameHeight) cap.set(10, 150) while True: success, img = cap.read() cv2.imshow("Result", img) if cv2.waitKey(1) & 0xFF == ord('q'): break
write
import cv2 img = cv2.imread("opencv-logo.png") # 用OpenCV读取opencv-logo.png图片并保存到变量img中 cv2.namedWindow("Image", cv2.WINDOW_NORMAL) # 给显示图片的窗口命名,并且采用默认模式 cv2.imshow("Image", img) # 展示图片 cv2.waitKey(0) # 等待用户按键退出 cv2.imwrite("output.jpg", img) # 将图片内容写入到output.jpg中
-
像素和数组分析
import cv2 img = cv2.imread("opencv-logo.png", 1) # 第2个参数是1表示使用图像的默认颜色和色彩通道,如果是0则表示以黑白形式读入该图片 print(img) # 会发现是一个数组 print(type(img)) # 类型是<class 'numpy.ndarray'> print(len(img)) # 表示数组的行 print(len(img[0])) # 表示数组的列 print(len(img[0][0])) # 表示通道数,这里是3,表示RGB红绿蓝3通道 print(img.shape) # 直接打印出这3项参数 print(img.dtype) # uint8,数据类型是8bit的无符号整数,也就是色彩从0~255 print(img[10, 5]) # 第10行第5列的像素,是一个有3个数的一维数组 print(img[:, :, 0]) # 打印出第一个通道的所有数据,即R通道在每个点上的数据 print(img.size) # 像素的个数
import numpy as np import cv2 # zeros(shape, dtype=float, order=‘C’) # shape:形状 shape = [a , b, m] a*b*通道数 # dtype:数据类型,可选参数,默认numpy.float64 # 全黑色图片 black = np.zeros([150, 200, 1], 'uint8') # 所有通道都是0,显示黑色 cv2.imshow("Black", black) print(black[0, 0, :]) # ones()返回一个全1的n维数组,同样也有三个参数:shape(用来指定返回数组的大小)、dtype(数组元素的类型)、 # order(是否以内存中的C或Fortran连续(行或列)顺序存储多维数据)。后两个参数都是可选的,一般只需设定第一个参数。和zeros一样 # 几乎黑色图片 ones = np.ones([150, 200, 3], 'uint8') cv2.imshow("Ones", ones) print(ones[0, 0, :]) # 全白色图片 white = np.ones([150, 200, 3], 'uint16') white *= (2 ** 16 - 1) # 点乘,所有通道都是最高,显示白色 cv2.imshow("White", white) print(white[0, 0, :]) # 全蓝色图片 color = ones.copy() # 深拷贝 color[:, :] = (255, 0, 0) # 蓝色通道最高,其余通道为0,显示蓝色 cv2.imshow("Blue", color) print(color[0, 0, :]) cv2.waitKey(0)
-
基本操作:颜色空间转换、模糊、边缘检测、膨胀、腐蚀
import cv2 import numpy as np # 彩色图像转换为灰度图像(以灰度图或者单通道图读入) # 对图像进行高斯模糊(去噪) # 计算图像梯度,根据梯度计算图像边缘幅值与角度 # 沿梯度方向进行非极大值抑制(边缘细化) # 双阈值边缘连接处理 # 二值化图像输出结果 img = cv2.imread("./lena.png") kernel = np.ones((5, 5), np.uint8) imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # cv2.cvtColor(p1,p2) 是颜色空间转换函数,p1是需要转换的图片,p2是转换成何种格式。 # cv2.COLOR_BGR2RGB 将BGR格式转换成RGB格式 # cv2.COLOR_BGR2GRAY 将BGR格式转换成灰度图片 # (7, 7)表示高斯矩阵的长与宽都是7,标准差取0 imgBlur = cv2.GaussianBlur(imgGray, (7, 7), 0) # 高斯模糊滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程 # 行canny边缘检测 # 很明显,Canny边缘检测的效果是很显著的。相比普通的梯度算法大大抑制了噪声引起的伪边缘, # 而且是边缘细化,易于后续处理。对于对比度较低的图像,通过调节参数,Canny算法也能有很好的效果。 # 参数说明: src表示输入的图片, # thresh1表示最小阈值,thresh2表示最大阈值,用于进一步删选边缘信息 imgCanny = cv2.Canny(img, 150, 200) # 腐蚀与膨胀属于形态学操作,所谓的形态学,就是改变物体的形状,形象理解一些:腐蚀=变瘦 膨胀=变胖 imgDialation = cv2.dilate(imgCanny, kernel, iterations=1) # 膨胀操作原理:存在一个kernel, # 在图像上进行从左到右,从上到下的平移, # 如果方框中存在白色,那么这个方框内所有的颜色都是白色 imgEroded = cv2.erode(imgDialation, kernel, iterations=1) # 在原图的每一个小区域里取最小值,由于是二值化图像,只要有一个点为0,则都为0, # 来达到瘦身的目的。因此在下面的例子中,我们就可以使用腐蚀来将图片中的一些毛刺或者说很细小的东西给去掉。 cv2.imshow("Gray Image", imgGray) cv2.imshow("Blur Image", imgBlur) cv2.imshow("Canny Image", imgCanny) cv2.imshow("Dialation Image", imgDialation) cv2.imshow("Eroded Image", imgEroded) cv2.waitKey(0)
-
改变大小
import cv2 import numpy as np img = cv2.imread("./shapes.png") print(img.shape) imgResize = cv2.resize(img, (1000, 500)) # 改变大小 print(imgResize.shape) imgCropped = img[46:119, 352:495] # 裁剪坐标为[y0:y1, x0:x1 print(imgCropped.shape) cv2.imshow("Image", img) cv2.imshow("Image Resize", imgResize) cv2.imshow("Image Cropped", imgCropped) cv2.waitKey(0)
-
增加图形和文字
import cv2 import numpy as np img = np.zeros((512, 512, 3), np.uint8) print(img) img[:] = 255, 0, 0 # 蓝色通道最大 # 线 cv2.line(img, (0, 0), (img.shape[1], img.shape[0]), (0, 255, 0), 3) # 方形 cv2.rectangle(img, (0, 0), (250, 350), (0, 0, 255), 2) # 圆形 cv2.circle(img, (400, 50), 30, (255, 255, 0), 5) # 文字 cv2.putText(img, " OPENCV ", (300, 200), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 150, 0), 3) cv2.imshow("Image", img) cv2.waitKey(0)
-
视角变换
import cv2 import numpy as np img = cv2.imread("./cards.jpg") width, height = 250, 350 # 数位的区别,一个在内存中占分别32和64个bits,也就是4bytes或8bytes # 数位越高浮点数的精度越高 pts1 = np.float32([[111, 219], [287, 188], [154, 482], [352, 440]]) pts2 = np.float32([[0, 0], [width, 0], [0, height], [width, height]]) # 透视变换(Perspective Transformation)是将成像投影到一个新的视平面(Viewing Plane), # 也称作投影映射(Projective Mapping)。如图1,通过透视变换ABC变换到A'B'C'。 # 将四个点组成的平面转换成另四个点组成的一个平面 matrix = cv2.getPerspectiveTransform(pts1, pts2) # 通过warpPerspective函数来进行变换 imgOutput = cv2.warpPerspective(img, matrix, (width, height)) cv2.imshow("Image", img) cv2.imshow("Output", imgOutput) cv2.waitKey(0)
-
图像拼接
import cv2 import numpy as np def stack_images(scale, img_array): rows = len(img_array) cols = len(img_array[0]) rows_available = isinstance(img_array[0], list) width = img_array[0][0].shape[1] height = img_array[0][0].shape[0] if rows_available: for x in range(0, rows): for y in range(0, cols): if img_array[x][y].shape[:2] == img_array[0][0].shape[:2]: img_array[x][y] = cv2.resize(img_array[x][y], (0, 0), None, scale, scale) else: img_array[x][y] = cv2.resize(img_array[x][y], (img_array[0][0].shape[1], img_array[0][0].shape[0]), None, scale, scale) if len(img_array[x][y].shape) == 2: img_array[x][y] = cv2.cvtColor(img_array[x][y], cv2.COLOR_GRAY2BGR) image_blank = np.zeros((height, width, 3), np.uint8) hor = [image_blank] * rows hor_con = [image_blank] * rows for x in range(0, rows): hor[x] = np.hstack(img_array[x]) ver = np.vstack(hor) else: for x in range(0, rows): if img_array[x].shape[:2] == img_array[0].shape[:2]: img_array[x] = cv2.resize(img_array[x], (0, 0), None, scale, scale) else: img_array[x] = cv2.resize(img_array[x], (img_array[0].shape[1], img_array[0].shape[0]), None, scale, scale) if len(img_array[x].shape) == 2: img_array[x] = cv2.cvtColor(img_array[x], cv2.COLOR_GRAY2BGR) hor = np.hstack(img_array) ver = hor return ver img = cv2.imread('./lena.png') imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) imgStack = stack_images(0.5, ([img, imgGray, img], [img, img, img])) # np.vstack():在竖直方向上堆叠 # # np.hstack():在水平方向上平铺 imgHor = np.hstack((img, img)) imgVer = np.vstack((img, img)) cv2.imshow("Horizontal", imgHor) cv2.imshow("Vertical", imgVer) cv2.imshow("ImageStack", imgStack) cv2.waitKey(0)