使用OpenCV for Python的第一个步骤

304 阅读10分钟

使用OpenCV for Python的第一步

无论你是想为自动驾驶汽车建立一个复杂的深度学习模型,还是一个实时人脸识别程序,或者为你的研究生项目制作你的图像处理软件,你都必须一路学习OpenCV。

OpenCV是一个巨大的图像和视频处理库,旨在与许多语言如python、C/C++、Java等一起工作。它是如此的流行和强大,以至于你所知道的许多涉及图像处理的应用程序都是以它为基础的。

开始使用OpenCV可能是一个挑战,主要是如果你依赖它的官方文档,它以繁琐和难以理解而闻名。

今天我们将学习如何使用OpenCV,我将尽力使之简单化。


安装OpenCV

现在是只用一个简单的命令来安装OpenCV的时候了:

pip3 install opencv-python

导入一个简单的图像

你需要学习的第一件事是导入一个简单的图像并使用OpenCV显示它。

代码是很简单的:

import cv2

# Read the image
img = cv2.imread("image.jpg")

# Display the image
cv2.imshow("Image", img)

# Wait for a keypress
cv2.waitKey(0)

# Clean up
cv2.destroyAllWindows()

读取我们的第一张图片

阅读完代码后,如果你认为我们所做的不仅仅是加载图像,你是对的。毕竟,用OpenCV加载一张图片只需要一行python代码:

img = cv2.imread("image.jpg")

那么,剩下的呢?嗯......我们要做的第一件事就是导入这个库。只有这样,我们才能使用imread 方法来读取图像,并将图像的路径作为唯一的参数传递。

如果我们现在停止程序,我们就已经加载了图像,但却什么也没做,所以相反,让我们至少把图像呈现在一个新的窗口中,这样用户就可以看到结果。为此,我们将使用cv2.imshow 并将窗口名称和图像作为参数传递。

最后,我们告诉Python不要退出程序,直到我们按下一个键或关闭窗口。然后我们通过销毁所有我们打开的窗口来清理一切。


加载视频

OpenCV不仅擅长处理图像,也擅长处理视频。视频流可以从视频文件中加载,也可以直接从视频源(如网络摄像头)加载。

在下一个例子中,我们将从网络摄像头加载一个视频,并在一个新的窗口中展示它:

import cv2

# Load the video stream
video = cv2.VideoCapture(0)

while(True):
   # Capture each frame as an image
   ret, frame = video.read()

   # show the image on the screen
   cv2.imshow('frame', frame)
     
   # Stop the playback when pressing ‘q’
   if cv2.waitKey(1) == ord('q'):
       Break

# Release the video from memory
video.release() 

# Clean up
cv2.destroyAllWindows()

代码是不言自明的,但让我们详细地回顾一下。我们使用方法VideoCapture 来加载视频资源。第一个参数定义了我们正在读取的输入。传递一个0 ,我们指的是主网络摄像头(如果存在的话)。如果你有多个网络摄像头连接,你可以使用12 ,等等。如果你的视频被捕获并保存在一个文件中,你可以传递一个带有文件路径的字符串。接下来,我们开始一个循环,这个循环只有在用户命令时才会结束,但后面会有更多的内容。这里重要的是循环内发生的事情。我们要做的第一件事是要求我们的VideoCapture ,读取一帧视频。在摄像机的情况下,它将是当时摄像机的快照,在视频文件的情况下,它将是当前的视频帧。

我们以与图像相同的方式从视频加载中读取的每一帧都是至关重要的,因为这意味着我们在处理视频时有整个OpenCV的函数库可以供我们使用。

例如,用read 捕获的帧的输出可以被传递到方法imshow ,就像我们在前面处理图像的例子中所做的那样。

漂亮!

现在视频正在播放,但没有办法离开while 循环,所以让我们通过检测q 键是否被按下来建立一个退出策略。如果是,那么我们就退出循环,进行清理活动。

我们有一个额外的清理步骤,即释放摄像机或视频文件,因为即使我们不再读取任何帧,我们仍然在内存中打开对象。我们可以通过使用VideoCapture 对象的方法release 来实现。


调整图像大小

改变图像大小的应用范围很广,从优化尺寸、缩放,甚至喂养神经网络来执行一些魔法。如果调整图像大小是你想要的,OpenCV就能满足你。

现在让我们看一个如何调整图像大小的例子:

import cv2
img = cv2.imread("image.jpg")
scale = 60
width = int(img.shape[1] * scale / 100)
height = int(img.shape[0] * scale / 100)
dim = (width, height)
resized_img = cv2.resize(img, dim, cv2.INTER_AREA)
cv2.imshow("Resized_Image", resized_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

调整图像的大小

这很简单,所以我们给它加了些味道,我们不是简单地将图像的大小调整到一个特定的尺寸,而是将图像按X的系数缩小(在这个例子中是60%)。请注意,如果我们针对的是特定的尺寸,那么代码会更简单。

resize ,该方法至少需要两个参数,要调整的图像和新的尺寸(以x和y为单位的元组)。我们可以选择传递第三个参数来定义插值,如resize函数文档中所述。


切换颜色空间

当我们用OpenCV读取图像时,我们把颜色看作是通道或图像阵列的深度,每个通道或维度对应一种颜色。最常见的颜色空间和你可能已经知道的是RGB,由3个通道组成:红、绿、蓝。但其他系统也可以在图像上表示颜色,如LABYCrCbHLSHSV,等等。它们中的每一个都有不同的特点,值得研究和学习。

在图像上设置颜色的一个更流行的选择是灰度,其中每个像素只有一个通道来定义。让我们看一个例子,说明我们如何将彩色图像转换成灰度图像:

import cv2
img = cv2.imread("image.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow("Gray", gray)
cv2.waitKey(0)
cv2.destroyAllWindows()

灰度图像

发生所有魔法的函数是cvtColor ,它需要两个参数,图像和颜色空间,并返回新的图像而不改变原始图像。幸运的是,OpenCV已经为每个已知的色彩空间转换定义了值。在我们的例子中,我们使用COLOR_BGR2GRAY ,它将BGR转换为GRAY。

那么什么是BGR?它是OpenCV加载图像的默认方式。


保存图像

我们经常需要在处理完图像后保存其结果,也许是在改变其色彩空间后,进行图像转换,或对该图像进行任何操作。

下面的代码向你展示了如何在将图像的颜色改为灰度后保存它:

import cv2
img = cv2.imread("image.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow("Gray", gray)
cv2.imwrite("image_gray.jpg", gray)
cv2.waitKey(0)
cv2.destroyAllWindows()

你可以看到,我们使用了一个名为imwrite 的函数,负责在指定了新保存的图像的路径后,将灰色图像保存在我们的计算机中。在这种情况下,我们需要保存的实际图像是变量灰色。


图像平滑

OpenCV提供了一些工具来平滑图像并帮助减少其中的噪音。这个过程是完全自动化的,所有复杂的工作方式都被封装在一个简单易用的函数中。

平滑图像的目的是提高其质量,虽然不是完美的,但在某些情况下,它可以是一个实质性的变化,是在进一步的过程中使用图像的关键。

下面是一个如何平滑图像的例子:

import cv2
img = cv2.imread("early_1800.jpg")
blur = cv2.blur(img, (5, 5))
cv2.imshow("Blur", blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像看起来好多了,但它是如何工作的呢?通过OpenCV库的方法blur ,它需要图像和内核大小作为参数。核大小是一个元组,用来反映x和y轴。请注意,不同的x和y的值会导致不同的输出,所以你必须对你的图像的这些值进行调整。

内核大小的作用是取一个小的像素区域(在我们的例子中是5x5),取这些像素的平均值,然后替换掉真实的一个(像素),得到新的小噪声图像。

还有其他方法来平滑图像,例如使用gaussianBlurmedianBlur ,其工作原理与此类似。


在图像上绘图

到目前为止,我们一直在玩图像,没有给它们添加任何新东西。现在是我们改变这种情况的时候了。OpenCV不仅允许我们对图像进行变换和效果,而且还允许我们改变它们或在它们上面绘图。

在图像上作画是很有用的,例如,如果你想做一个物体跟踪程序或人脸识别程序,你想画一个方形或形状来突出被识别的物体。

让我们在图像上画几个几何图形来展示它是如何工作的。

画一条线

我们将尝试使用line 函数在图像上画一条线:

import cv2
img = cv2.imread("image.jpg")
line = cv2.line(img, (20, 20), (150, 150), (255, 0, 0), 5)
cv2.imshow("Line", line)
cv2.waitKey(0)
cv2.destroyAllWindows()

line 函数希望得到图像和另外四个参数:线的起点(x1, y1),线的终点(x2, y2),线的颜色(对我们的图像来说是BGR),以及它的厚度(像素)。

绘制一个矩形

我认为矩形是最常用的形状,至少在人工智能领域是这样,因为它们通常被用来追踪图像上的物体,如人脸、汽车或交通标志。它们也超级容易使用。下面是一个例子。

import cv2 as cv
img = cv2.imread("image.jpg")
rectangle = cv2.rectangle(img, (200, 200), (450, 450), (255, 0, 0), 5)
cv2.imshow("Rectangle", rectangle)
cv2.waitKey(0)
cv2.destroyAllWindows()

rectangle 函数与line 函数非常相似。它希望得到图像和另外四个参数:矩形的左上角(x1, y1),右下角(x2, y2),线条的颜色(对我们的图像来说是BGR),以及它的厚度(像素)。###.绘制圆圈 最后,我们将在图像上绘制一个小圆圈,当你追踪一个圆形物体(如球)时,这个圆圈有时很有用:

import cv2
img = cv2.imread("image.jpg")
circle = cv2.circle(img, (300, 300), 50, (255, 0, 0), 5)
cv2.imshow("Circle", circle)
cv2.waitKey(0)
cv2.destroyAllWindows()

同样,所有这些函数都是非常相似的。要在图像上呈现一个圆,我们使用circle ,该函数需要图像和另外四个参数:圆的中心点(x,y),半径(像素),颜色和线的厚度。

总结

OpenCV是一个用于处理图像和视频的令人兴奋和强大的库。它的使用范围很广,从一个简单的辅助库来执行图像操作到实现最先进的计算机视觉算法。

今天我们只是介绍了这个库的一小部分功能。如果你喜欢这种阅读方式,我建议你看看我的文章《OpenCV的基本功能》,这将使你对这个库的了解更加深入。

计算机视觉是一个让我着迷的话题,我将在未来写更多关于OpenCV的文章,敬请关注。

谢谢你的阅读!