计算机视觉与OpenCV入门

计算机视觉是人工智能的一个分支,它使计算机能够从图像、视频和其他视觉输入中提取有意义的信息,并采取必要的行动。例如,自动驾驶汽车、自动交通管理、监控、基于图像的质量检查等。

什么是OpenCV?

OpenCV是一个主要针对计算机视觉的库。它包含了在计算机视觉工作中需要的所有工具。'Open'代表开源,'CV'代表计算机视觉。

将学习什么?

本文包含了使用OpenCV库开始计算机视觉所需的一切。将对计算机视觉感到更自信、更高效。所有的代码和数据都在这里。

图像读取与显示

首先,来了解如何读取和显示图像,这是计算机视觉的基础。

import numpy as np import cv2 as cv import matplotlib.pyplot as plt img = cv.imread('../input/images-for-computer-vision/tiger1.jpg') print(type(img)) print(img.shape)

'img'包含了以numpy数组形式的图像。让打印它的类型和形状。numpy数组的形状为(667, 1200, 3),其中,667是图像高度,1200是图像宽度,3是通道数。在这种情况下,有RGB通道,所以有3个。原始图像以RGB形式存在,但OpenCV默认以BGR读取图像,所以需要在显示之前将其转换回RGB。

在图像上绘制

可以在图像上绘制线条、形状和文本。

# 绘制矩形 color = (240, 150, 240) # 矩形的颜色 cv.rectangle(img, (100, 100), (300, 300), color, thickness=10, lineType=8) # 填充矩形使用thickness = -1 # 绘制圆形 color = (150, 260, 50) cv.circle(img, (650, 350), 100, color, thickness=10) # 填充圆形使用thickness = -1 # 添加文本 color = (50, 200, 100) font = cv.FONT_HERSHEY_SCRIPT_COMPLEX cv.putText(img, 'Save Tigers', (200, 150), font, 5, color, thickness=5, lineType=20) img_convert = cv.cvtColor(img, cv.COLOR_BGR2RGB) plt.imshow(img_convert)

图像混合

还可以混合两个或更多的图像。图像不过是数字,可以加、减、乘、除数字,因此也可以混合图像。需要注意的是,图像的大小应该相同。

def myplot(images, titles): fig, axs = plt.subplots(1, len(images), sharey=True) fig.set_figwidth(15) for img, ax, title in zip(images, axs, titles): if img.shape[-1] == 3: img = cv.cvtColor(img, cv.COLOR_BGR2RGB) # OpenCV读取图像为BGR,所以转换回RGB else: img = cv.cvtColor(img, cv.COLOR_GRAY2BGR) ax.imshow(img) ax.set_title(title) img1 = cv.imread('../input/images-for-computer-vision/tiger1.jpg') img2 = cv.imread('../input/images-for-computer-vision/horse.jpg') img1_resize = cv.resize(img1, (img2.shape[1], img2.shape[0])) img_add = cv.add(img1_resize, img2) img_subtract = cv.subtract(img1_resize, img2) img_multiply = cv.multiply(img1_resize, img2) img_divide = cv.divide(img1_resize, img2) img_blend = cv.addWeighted(img1_resize, 0.3, img2, 0.7, 0) # 30%老虎和70%马 myplot([img1_resize, img2], ['老虎', '马']) myplot([img_add, img_subtract, img_multiply, img_divide, img_blend], ['加法', '减法', '乘法', '除法', '混合'])

乘法图像几乎是白色的,除法图像是黑色的,这是因为白色代表255,黑色代表0。当乘以两个图像的像素值时,得到一个更高的数字,所以它的颜色变成白色或接近白色,除法图像则相反。

图像变换

图像变换包括平移、旋转、缩放、剪切和翻转图像。

img = cv.imread('../input/images-for-computer-vision/tiger1.jpg') width, height, _ = img.shape # 平移 M_translate = np.float32([[1, 0, 200], [0, 1, 100]]) # 200=>沿x轴平移,100=>沿y轴平移 img_translate = cv.warpAffine(img, M_translate, (height, width)) # 旋转 center = (width / 2, height / 2) M_rotate = cv.getRotationMatrix2D(center, angle=90, scale=1) img_rotate = cv.warpAffine(img, M_rotate, (width, height)) # 缩放 scale_percent = 50 width = int(img.shape[1] * scale_percent / 100) height = int(img.shape[0] * scale_percent / 100) dim = (width, height) img_scale = cv.resize(img, dim, interpolation=cv.INTER_AREA) # 翻转 img_flip = cv.flip(img, 1) # 0:沿水平轴,1:沿垂直轴,-1:先垂直后水平 # 剪切 srcTri = np.array([[0, 0], [img.shape[1] - 1, 0], [0, img.shape[0] - 1]]).astype(np.float32) dstTri = np.array([[0, img.shape[1] * 0.33], [img.shape[1] * 0.85, img.shape[0] * 0.25], [img.shape[1] * 0.15, img.shape[0] * 0.7]]).astype(np.float32) warp_mat = cv.getAffineTransform(srcTri, dstTri) img_warp = cv.warpAffine(img, warp_mat, (height, width)) myplot([img, img_translate, img_rotate, img_scale, img_flip, img_warp], ['原始图像', '平移后的图像', '旋转后的图像', '缩放后的图像', '翻转后的图像', '剪切后的图像'])

图像预处理

图像预处理包括阈值处理、滤波等操作。

在阈值处理中,小于阈值的像素值变为0(黑色),大于阈值的像素值变为255(白色)。选择的阈值是150,但可以选择任何其他数字。

import plotly.graph_objects as go from plotly.subplots import make_subplots def plot_3d(img1, img2, titles): fig = make_subplots(rows=1, cols=2, specs=[[{'is_3d': True}, {'is_3d': True}]], subplot_titles=[titles[0], titles[1]], ) x, y = np.mgrid[0:img1.shape[0], 0:img1.shape[1]] fig.add_trace(go.Surface(x=x, y=y, z=img1[:, :, 0]), row=1, col=1) fig.add_trace(go.Surface(x=x, y=y, z=img2[:, :, 0]), row=1, col=2) fig.update_traces(contours_z=dict(show=True, usecolormap=True, highlightcolor="limegreen", project_z=True)) fig.show() img = cv.imread('../input/images-for-computer-vision/simple_shapes.png') _, img_threshold = cv.threshold(img, 150, 255, cv.THRESH_BINARY) plot_3d(img, img_threshold, ['原始图像', '阈值图像=150'])

应用阈值处理后,值为150的值变为255。

图像滤波是通过改变像素值来改变图像的外观。每种类型的滤波器根据相应的数学公式改变像素值。这里不详细介绍数学知识,但将展示每个滤波器如何通过3D可视化工作。如果对滤波器背后的数学感兴趣,可以查看相关资料。

img = cv.imread('../input/images-for-computer-vision/simple_shapes.png') # 高斯滤波器 ksize = (11, 11) # 两者都应该是奇数 img_gaussian = cv.GaussianBlur(img, ksize, 0) plot_3d(img, img_gaussian, ['原始图像', '高斯图像']) # 中值滤波器 ksize = 11 img_median = cv.medianBlur(img, ksize) plot_3d(img, img_median, ['原始图像', '中值模糊']) # 双边滤波器 img_bilateral = cv.bilateralFilter(img, d=5, sigmaColor=50, sigmaSpace=5) myplot([img, img_bilateral], ['原始图像', '双边模糊图像']) plot_3d(img, img_bilateral, ['原始图像', '双边模糊'])

高斯滤波器:通过去除细节和噪声来模糊图像。更多细节,可以阅读相关资料。中值滤波器:非线性过程,有助于减少冲动性或椒盐噪声。双边滤波器:保持边缘,并减少噪声平滑。简而言之,滤波器有助于减少或去除噪声,这是亮度或颜色的随机变化,这被称为平滑。

特征检测是一种在每个图像点进行局部决策的方法,通过计算图像信息的抽象。例如,对于人脸图像,特征是眼睛、鼻子、嘴唇、耳朵等,尝试识别这些特征。

img = cv.imread('../input/images-for-computer-vision/simple_shapes.png') img_canny1 = cv.Canny(img, 50, 200) # 在将图像输入Canny之前平滑图像以去除噪声 filter_img = cv.GaussianBlur(img, (7, 7), 0) img_canny2 = cv.Canny(filter_img, 50, 200) myplot([img, img_canny1, img_canny2], ['原始图像', 'Canny边缘检测器(无平滑)', 'Canny边缘检测器(有平滑)'])

这里使用的是Canny边缘检测器,它是一个边缘检测算子,使用多阶段算法检测图像中的广泛边缘。它由John F. Canny在1986年开发。这里不详细介绍Canny的工作原理,但关键是它用于提取边缘。要了解更多关于其工作原理的信息,可以查看相关资料。在应用Canny边缘检测方法之前,平滑图像以去除噪声。从图像中可以看到,平滑后得到了清晰的边缘。

img = cv.imread('../input/images-for-computer-vision/simple_shapes.png') img_copy = img.copy() img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) _, img_binary = cv.threshold(img_gray, 50, 200, cv.THRESH_BINARY) # 腐蚀和膨胀以平滑轮廓 img_binary_erode = cv.erode(img_binary, (10, 10), iterations=5) img_binary_dilate = cv.dilate(img_binary, (10, 10), iterations=5) contours, hierarchy = cv.findContours(img_binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) cv.drawContours(img, contours, -1, (0, 0, 255), 3) # 在原始图像上绘制轮廓 myplot([img_copy, img], ['原始图像', '图像中的轮廓'])
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485