当前位置: 首页 > 后端技术 > Python

Opencv学习指南入门(一):基本图像操作

时间:2023-03-26 13:37:44 Python

(注:本文节选自AdrianRosebrock的教程文章翻译后)1.在Ubuntu16.04系统上安装OpenCV和imutils(一)opencv安装在我有在我之前的博文中介绍过,可以阅读;(2)安装imutils:pipinstallimutils如果你使用的是虚拟环境,进入虚拟环境后记得安装imutils。简单介绍一下imutils:它是基于opencv的。封装使得一些图像处理方法更加方便易用2.查看我们的opencv工程结构假设我们将下载的源码存放在“Download”文件夹中,执行如下命令:cddownloadunzipopencv-tutorial.zipcdopencv-tutorialtree的第一个脚本opencv_tutorial_01.py将使用电影《侏罗纪公园》中的图像(jp.png)进行基本图像处理操作。第二个脚本opencv_tutorial_02.py将展示如何使用这些图像处理块来创建OpenCV应用程序来计算俄罗斯方块图像(tetris_blocks.png)中的对象数量。3.加载并显示图像首先在文本编辑器或IDE中打开opencv_tutorial_01.py:#导入必要的包importimutilsimportcv2#加载并显示图像大小#将图像表示为包含h,w,die变量的多维numpy数组"image"#Shape参数包括行(高)x列(宽)x通道(深)image=cv2.imread("jp.png")(h,w,d)=image.shapeprint("width={},height={},depth={}".format(w,h,d))#在屏幕上显示图像,鼠标点击到图像窗口#按任意键继续执行程序cv2.imshow("Image",image)cv2.waitKey(0)深度是通道数——在我们的例子中它是3,因为我们使用3个颜色通道:蓝色、绿色和红色(RGB)。打印输出width,height,depth:width=600,height=322,depth=3cv2.waitKey(0):等待key,这个很重要,否则我们的图像出现和消失的速度会比我们看到图像快4.访问单个像素所有图像都是由像素组成的,一张640x480的图像有640列(宽)和480行(高),有640×480=307200个像素,灰度图中每个像素都有一个代表灰度值。在OpenCV中,有256个灰度(从0到255)。因此,灰度图像将具有与每个像素关联的灰度值。彩色图像中的像素具有附加信息,并且在学习图像处理时可以很快熟悉多个颜色空间。为简单起见,我们只考虑RGB颜色空间。在OpenCV彩色图像中,RGB(红、绿、蓝)颜色空间中的每个像素都有一个三元组(B,G,R),注意顺序是BGR而不是RGB。BGR三元组中的每个值都在[0,255]范围内。OpenCV中RGB图像中的每个像素有多少种颜色可能性?很简单:256×256×256=16777216图像坐标系规定左上角为(0,0)#访问x=50(w),y=100(h)处的RGB像素#OpenCV使用BGR而不是RGB按顺序存储图像(B,G,R)=image[100,50]print("R={},G={},B={}".format(R,G,B))之前已知图片尺寸为width=600,height=322,depth=3。我们可以通过指定坐标来访问数组中的每个像素值,只要它们在最大宽度和高度之内即可。指定图像像素点的格式为:image[Y,X]。在终端打印出该像素点的RGB值:R=41,G=49,B=375。提取感兴趣区域(ROI)提取“感兴趣区域”(ROI)是图像处理中的一项重要技能。例如,假设您正在识别电影中的面孔。首先,您将运行人脸检测算法来查找您正在使用的所有帧中的人脸坐标。然后您需要提取人脸ROI并保存或处理它们。手动提取ROI是通过数组切片实现的:#从输入图像中提取一个100*100的感兴趣区域,#从x=320,y=60到x=420,y=160,显示图像roi=image[60:160,320:420]cv2.imshow("ROI",roi)cv2.waitKey(0)数组切片的格式为:image[startY:endY,startX:endX],注意前面close和然后打开6.Adjustimagesizeadjustment图像大小很重要有很多原因。首先,我们可能需要调整大图像的大小以适应屏幕。由于要处理的像素较少,图像较小的图像处理速度也更快。在深度学习的情况下,我们经常忽略长宽比来调整图像的大小以适应网络的体积,这要求图像是方形的并且具有一定的尺寸。#忽略宽高比并将原始图像调整为200x200像素:resized=cv2.resize(image,(200,200))cv2.imshow("FixedResizing",resized)cv2.waitKey(0)由于忽略长宽比,生成的图像已经失真。假设您要在保持纵横比不变的情况下将600像素宽的图像调整为300像素宽。#固定调整大小扭曲纵横比,所以让我们将宽度调整为300px,#但得到hightr=300.0/wdim=(300,int(h*r))resized=cv2.resize(image,dim)cv2.imshow("AspectRatioresize",resized)cv2.waitKey(0)我们计算新的宽度和旧的宽度的比例(刚好是0.5)。这里我们指定新图像的维度dim。我们知道我们想要一个300像素宽的图像,但我们必须乘以该比例来计算新的高度h。在cv2.resize函数中输入dim(图像的维度),我们现在得到一个名为resized的新图像,它是未失真的。但是我们能否使调整大小时保持纵横比的过程更容易?使用imutils中的函数:imutils.resize#手动计算宽高比可能很麻烦,#所以让我们使用#imutils库代替resized=imutils.resize(image,width=300)cv2.imshow("ImutilsResize",resized)cv2.waitKey(0)保留宽高比,调整图片大小,只需要提供图片的宽或高作为参数7.旋转图片#首先计算图片的中心,"//"表示四舍五入#构造旋转矩阵#最后应用warpAffine函数旋转图像center=(w//2,h//2)M=cv2.getRotationMatrix2D(center,-45,1.0)rotated=cv2.warpAffine(image,M,(w,h))cv2.imshow("OpenCVRotation",rotated)cv2.waitKey(0)-45表示将图像顺时针旋转45度。回想一下中学关于单位圆的信息,正角是逆时针方向,负角是顺时针方向。#使用imutils进行同样的操作rotated=imutils.rotate(image,-45)cv2.imshow("ImutilsRotation",rotated)cv2.waitKey(0)但是以上操作都会导致图片被裁剪,使用imutils.rotate_bound函数保持整个图像可见。:rotated=imutils.rotate_bound(image,45)cv2.imshow("ImutilsBoundRotation",rotated)cv2.waitKey(0)8.平滑图像在很多图像处理场合,我们必须对图像进行模糊处理,以降低高度这使得它我们的算法更容易检测和理解图像的实际内容。在OpenCV中模糊图像非常容易,并且有多种方法可以做到这一点。#对图像应用具有11x11核的高斯模糊以使其平滑并减少高频噪声blurred=cv2.GaussianBlur(image,(11,11),0)cv2.imshow("Blurred",blurred)cv2.waitKey(0)较大的内核会产生更模糊的图像,较小的内核会产生不太模糊的图像。9.在图像上绘制我们将在输入图像上绘制矩形、圆形和线条,我们还将在图像上叠加文本。在继续使用OpenCV绘制图像之前,请注意图像上的绘制操作是直接执行的。所以在每个代码块的开头,我们制作原始图像的副本并将副本存储为输出。然后,我们继续绘制输出图像,以免破坏原始图像。(1)在IanMalcolm的脸上画一个矩形:#在男主角的脸上画一个矩形,线宽为2output=image.copy()cv2.rectangle(output,(320,60),(420,160),(0,0,255),2)cv2.imshow("Rectangle",output)cv2.waitKey(0)在OpenCV中绘制矩形比较简单,使用预先计算好的坐标,到cv2.rectangle函数提供以下参数:img:要绘制的目标图像outputpt1:起始像素坐标,在我们的例子中为左上角,(320,60)pt2:结束像素坐标,右下角像素为(420,160)color:BGRtuple,red(0,0,255)thickness:线的粗细(负值会形成一个实心矩形),这里是2因为我们使用的是OpenCV函数而不是NumPy操作,所以我们可以提供坐标在(x,y)顺序而不是(y,x)顺序,因为我们无法直接操作或访问NumPy数组来为我们处理这些事情。(2)在EllieSattler博士的脸前放置一个蓝色实心圆:#在x=300,y=150处画一个蓝色实心圆output=image.copy()cv2.circle(output,(300,150),20,(255,0,0),-1)cv2.imshow("Circle",output)cv2.waitKey(0)画一个圆,需要给cv2.circle提供如下参数:img:图像名称center:圆的中心坐标,这里是(300,150)radius:圆的半径(以像素为单位),设置为20个像素值color:圆的颜色,蓝色(255,0,0)thickness:线的粗细,使用负值(-1),所以圆是实心的(3)画一条红线穿过Ellie的头,经过她的眼睛,一直到Ian的手:#从x=60,y=20画一条宽度为5的红线到x=400,y=200output=image.copy()cv2.line(output,(60,20),(400,200),(0,0,255),5)cv2.imshow("Line",output)cv2.waitKey(0)和矩形一样,有两个参数,颜色和线宽。(4)在图像上叠加文字:如果做人脸识别,你可能需要把人的名字画在人的脸上,或者如果你在计算机视觉方面的职业发展,你可以建立一个图像分类器或物体检测器,需要画包含类别名称和概率的文本。#在图像上绘制文本output=image.copy()cv2.putText(output,"OpenCV+JurassicPark!!!",(10,25),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,255,0),2)cv2.imshow("Text",output)cv2.waitKey(0)putText函数负责在图片上绘制文字,需要的参数:img:图片名称text:要在图片上写入/绘制的文字串pt:文字字体起点:cv2.FONT_HERSHEY_SIMPLEX字体经常用到,可以去官网查看运行即可,最后贴上源码:#USAGE#pythonopencv_tutorial_01.py#导入必要的包importimutilsimportcv2#加载输入图像并显示其尺寸,请记住#images表示为具有#shapeno的多维NumPy数组。行数(高)x数列(宽度)x数通道(深度)图像=cv2。imread("jp.png")(h,w,d)=图像。shapeprint("width={},height={},depth={}".format(w,h,d))#将图像显示到我们的屏幕上——我们需要点击由OpenCV打开的窗口并按下我们键盘上的一个键继续执行cv2.imshow("Image",image)cv2.waitKey(0)#access位于x=50,y=100的RGB像素,请记住#OpenCV以BGR顺序存储图像而不是RGB(B,G,R)=image[100,50]print("R={},G={},B={}".format(R,G,B))#从#输入图像中提取一个100x100像素的正方形ROI(感兴趣区域),起始于x=320,y=60,结束于x=420,y=160roi=image[60:160,320:420]cv2.imshow("ROI",roi)cv2.waitKey(0)#resizetheimageto200x200px,ignoringaspectratioresized=cv2.resize(image,(200,200))cv2.imshow("FixedResizing",resized)cv2.waitKey(0)#固定调整大小和扭曲宽高比所以我们将宽度调整为300px但根据宽高比计算新高度=300.0/wdim=(300,int(h*r))resized=cv2.resize(image,dim)cv2.imshow("AspectRatioResize",resized)cv2.waitKey(0)#手动计算纵横比即可痛苦所以让我们改用#imutils库resized=imutils.resize(image,width=300)cv2.imshow("ImutilsResize",resized)cv2.waitKey(0)#让's使用OpenCV将图像顺时针旋转45度,首先#计算图像中心,然后构建旋转矩阵,#最后应用仿射warpcenter=(w//2,h//2)M=cv2.getRotationMatrix2D(center,-45,1.0)rotated=cv2.warpAffine(image,M,(w,h))cv2.imshow("OpenCVRotation",rotated)cv2.waitKey(0)#旋转也可以通过imutils轻松完成coderotated=imutils.rotate(image,-45)cv2.imshow("ImutilsRotation",rotated)cv2.waitKey(0)#OpenCV不会“关心”我们的旋转图像是否在旋转后被剪裁#所以我们可以改用另一个imutils便利函数可以帮助#usoutrotated=imutils.rotate_bound(image,45)cv2.imshow("ImutilsBoundRotation",rotated)cv2.waitKey(0)#将具有11x11内核的高斯模糊应用到图像以平滑it,#在降低高频噪声时很有用blurred=cv2.GaussianBlur(image,(11,11),0)cv2.imshow("Blurred",blurred)cv2.waitKey(0)#画一个2px厚的面部周围的红色矩形output=image.copy()cv2.rectangle(output,(320,60),(420,160),(0,0,255),2)cv2.imshow("Rectangle",output)cv2.waitKey(0)#在图像上以#x=300,y=150output=image.copy()cv2.circle(output,(300,150),20,(255)为中心绘制一个蓝色的20px(填充)圆,0,0),-1)cv2.imshow("Circle",output)cv2.waitKey(0)#从x=60,y=20到x=400,y=200画一条5px粗的红线output=image.copy()cv2.line(output,(60,20),(400,200),(0,0,255),5)cv2.imshow("Line",output)cv2.waitKey(0)#draw图像上的绿色文本output=image.copy()cv2.putText(output,"OpenCV+JurassicPark!!!",(10,25),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,255,0),2)cv2.imshow("文本",输出)cv2.waitKey(0)