python图像处理入门:opencv图像机器学习
本章介绍图像的基本概念和基本操作。 我们将首先提供像素等图像基础知识的清晰定义。 接下来,我们将深入讲解如何使用 OpenCV 库读取、显示和保存图像。 然后我们将继续使用 OpenCV 在图像上绘制形状的实际任务,重点是矩形、圆形和其他基本形状等主题。
1. 图像和像素简介
什么是图像? 用非技术术语来说,图像是指场景、物体或人的视觉表示,它使我们能够更好地理解周围的世界。在数字环境中,图像是像素的多维阵列。
像素是图像的构建块。 像素是数字图像的最小单位,包含有关其颜色和位置的信息。 当多个像素在二维网格中聚集在一起时,它们就形成了完整的图像。 数字图像中的像素以网格图案排列以创建整体图像。 每个像素都包含特定的颜色信息,它们一起形成完整的图像。
像素通常用于表示灰度或彩色图像。 灰度图像通常表示为二维像素网格,而彩色图像通常表示为多维矩阵。 在灰度图像中,每个像素都分配有0 到 255 之间的值,表示该点图像的强度。 值 0 表示没有强度,导致黑色像素,而值255表示最大强度,导致纯白色像素。
在彩色图像中,每个像素由三个或四个值的组合表示,最常见的颜色空间是 RGB 颜色空间。 在此空间中,使用表示红色、绿色和蓝色通道强度的三个值来表示单个像素。 每个值的范围从 0 到 255,表示像素中存在的每种颜色的数量。 典型的 RGB 像素可以用(红、绿、蓝)格式表示。
例如,具有 (0,0,0) 值的颜色表示黑色,因为所有颜色的强度均为 0,而 (255,255,255) 表示白色图像,因为所有颜色都有最大值。
让我们看几个关于如何在 RGB 颜色空间中表示颜色的示例:
-
(255,0,0) 产生纯红色,因为红色处于最大值,而绿色和蓝色处于 0。
-
(0,255,0) 产生纯绿色。
-
(0,0,255) 产生纯蓝色。
-
(255,255,0) 产生黄色,因为它是红色和绿色的组合。
-
(128,128,128) 代表灰色。
PPI(即每英寸像素 Pixels per Inch)表示单英寸数字图像中存在的像素数。 较高的 PPI 意味着每英寸有更多的像素,从而产生更平滑、更细致的图像。 相反,较低的 PPI 意味着像素较大且每英寸的像素较少,从而导致图像细节较少且清晰度较差。
分辨率是一个术语,用于描述构成图像的像素总数。 分辨率越高,像素越多,从而产生更详细和高质量的图像。 分辨率通常以每英寸像素 (PPI) 或每英寸点数 (DPI) 来衡量。 当图像的分辨率较低时,意味着像素较少,因此图像的细节较少。
长宽比是指图像的宽度和高度之间的比例关系,它决定了图像的整体形状。 它通常表示为用冒号分隔的两个数字(例如 4:3 或 16:9),表示图像或屏幕的宽度和高度。 例如,纵横比为 4:3 的图像的宽度为每3 个单位的高度对应 4 个单位的长度。 宽高比用于确保在不同设备上显示图像时图像正确适合显示尺寸。
数字图像的像素数量一直在迅速增加。 第一台商用数码相机 Dycam Model 1 的分辨率仅为 0.01兆像素,而当今的高端相机可以捕获分辨率为 100兆像素或更高的图像。
2. 加载和显示图像
是时候开始处理图像了! 在本书中,当我们引导您完成探索和操作图像的过程时,您将获得实践经验。 在我们继续前进时,请务必自行实现代码示例,因为这将有助于巩固您对我们将要介绍的概念的理解。
2.1 Imread()
要开始使用OpenCV处理图像,我们需要使用imread() 函数。通过该函数,我们可以将图像加载到我们的程序中:
cv2.imread(path, flag=cv2.IMREAD_COLOR)
参数:
-
path: 字符串,表示要读取图像的路径。
-
flag: 可选参数, 指定读取图像的方式。
cv2.IMREAD_COLOR (1): 以 BGR 格式加载图像。这是该函数的默认格式。
cv2.IMREAD_GRAYSCALE (0):以灰度格式加载图像: 以灰度格式加载图像。
cv2.IMREAD_UNCHANGED (-1):以原始格式加载图像: 以原始格式加载图像,通常用于包含 alpha 通道。
cv2.imread(path, 0)
这将以灰度格式加载图像。
2.2 imshow
cv2.imshow(winname, mat)
参数:
-
Winname:显示图像的窗口名称。
-
Mat: 表示我们要显示的图像的 NumPy 数组。
2.3 imwrite
Imwrite 用于将图像保存到系统中。
cv2.imwrite(filename, img, params=None)
参数:
-
Filename:表示要保存的图像路径的字符串
-
Img: 表示我们要写入的图像的NumPy数组。
-
Params: 可选参数,用于指定图像文件的格式和压缩参数。默认值为None。
示例代码
在本练习中,我们将使用之前学习的代码加载图像并显示图像:
import cv2 # Using imread to read out image img = cv2.imread("../img/dog.jpg") # Print the shape of the image print(img.shape) # Displaying the image cv2.imshow("Dog Image", img) # Wait until a key is pressed cv2.waitKey(0) # Close all Windows cv2.destroyAllWindows()
2.4 WaitKey
WaitKey是OpenCV程序中的一个函数,用于让用户在特定时间内或按下某个键之前显示一个窗口。如果没有 waitKey,图像或视频会在用户来得及观看之前立即关闭。
它只接受一个整数参数,即窗口保持打开的毫秒数。如果给定的参数为0或根本没有给定参数,函数将等待按键按下后再关闭窗口。
2.5 DestroyAllWindows
DestroyAllWindows是一条简单的命令,用于关闭OpenCV在执行代码期间打开的所有窗口。该命令不需要任何参数。
我们已经成功运行了第一段 OpenCV 代码,现在可以读取并显示图像了。
试试看 现在尝试以不同的路径将前面的图像写入光盘。
3 用像素操作图像
图像在 Python 中存储为 NumPy 数组,这意味着图像元素可以像 NumPy 数组一样被索引。通过图像索引,我们可以操作图像中的单个像素或某个像素区域。
3.1 访问单个像素
要访问图像中的某个像素,我们可以使用类似的 img[row, col] 索引。使用此方法访问像素值将返回一个包含像素值的 NumPy 数组:
import cv2 # Load an image in grayscale mode img = cv2.imread('../img/dog.jpg') # Get the pixel value at x=75, y=25 pixel_value = img[25, 75] #Print this value print(pixel_value) #Manipulate value of this pixel img[25, 75] = 0 #Rechecking value print(pixel_value)
结果:
[120 165 222] [0 0 0]
对于RGB图像,前面的代码行将返回包含三个值的数组,而对于灰度图像,它将只返回值,例如30。
我们还可以使用索引修改像素值。我们可以为某个像素赋值,如下所示:
img[5,7] = 255
如果img是灰度图像,这将为像素赋值255。如果图像img是BGR 格式,那么三个颜色通道的值都将设置为 255。
如果我们想在 RGB 图像中设置特定值,可以使用该特定颜色的颜色代码:
img[5,7] = [0,255,0]
这将把绿色通道值设置为 255,其他两个通道设置为 0,从而得到纯绿色像素。
3.2 访问感兴趣区域 (ROI Region of Interest)
现在,我们将讨论如何通过使用索引定义感兴趣区域 (ROI) 来操作图像的整个区域。我们经常需要操作图像的特定区域,而不是单个像素或整个图像。
import cv2 # Load image img = cv2.imread('../img/dog.jpg') # Define index values x=50 y=60 w=75 h=75 # Extract ROI from the image roi = img[y:y+h,x:x+w] # Print shape of the extracted ROI print(roi.shape) # Assigning a colour to a different ROI img[100:150,150:200] = (255,255,0) cv2.imshow('Extracted ROI rectangle', roi) cv2.imshow('Image with ROI colour', img) cv2.waitKey(0) cv2.destroyAllWindows()
3.3 在OpenCV中绘图
在本节中,我们将学习如何使用 OpenCV 绘制形状。我们可以使用 OpenCV 设计各种形状,包括线、圆、矩形和多边形,还可以自定义它们的大小和颜色。使用 OpenCV 还可以在照片上添加文字。形状有多种用途,包括注释照片和强调照片的特定区域。
首先,我们将创建一张空白画布,在上面绘制各种形状。或者,也可以加载一张图片,然后在上面绘制形状。
为了创建绘制形状的画布,我们可以使用 NumPy 创建一个 NumPy 数组。然后,我们可以使用各种方法在 NumPy 画布上绘图:
canvas = np.zeros((600, 600, 3), dtype=np.uint8)
我们使用 np.zeros 函数创建画布。这是一个 NumPy 函数,用于创建一个具有特定形状和数据类型的 NumPy 数组。在本例中,我们创建了一个具有 "np.uint8 "数据类型的形状数组(600,600,3)。该数据类型对应于 8 位无符号整数,取值范围为 0 至 255。
3.4 线条(Line)
我们使用 cv2.line 命令在图像上创建线条。该命令提供多个参数,让我们可以自定义线条,以满足我们的特定需求和要求。
参数:
-
Img: 绘制线条的图像。
-
Pt1:线条的起始坐标: 线条的起始坐标。格式为 tuple (x,y)。
-
Pt2: 线条的终点坐标。格式为 tuple (x,y)。
-
Color:线条的颜色。采用元组(B、G、R)格式。
-
厚度(Thickness): 线条的厚度(像素)。这是一个可选参数,默认值为 1。
-
lineType(线条类型 线条的类型。我们将不使用此参数,可将其保留为默认值。
-
Shift(移位): 线条坐标中的小数位数。我们将不使用此参数,默认值为 0。
cv2.line(img, pt1, pt2, color, thickness=1, lineType = cv2.LINE_8, shift = 0)
实例:
import numpy as np import cv2 # Create a black canvas canvas = np.zeros((600, 500, 3), dtype=np.uint8) # Define the vertices of the triangle p1 = (250, 100) p2 = (100, 400) p3 = (400, 400) # Draw the lines using cv2.line() cv2.line(canvas, p1, p2, (0, 255, 0), 1) cv2.line(canvas, p3, p1, (255, 0, 0), 3) cv2.line(canvas, p2, p3, (255, 255, 255), 10) # Display the image cv2.imshow("Triangle", canvas) cv2.waitKey(0) cv2.destroyAllWindows()
参考资料
软件测试精品书籍文档下载持续更新 https://github.com/china-testing/python-testing-examples 请点赞,谢谢!
本文涉及的python测试开发库 谢谢点赞! https://github.com/china-testing/python_cn_resouce
python精品书籍下载 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
Linux精品书籍下载 https://www.cnblogs.com/testing-/p/17438558.html
3.5 矩形(rectangle)
在 OpenCV 中,绘制矩形与绘制直线类似。我们可以使用 cv2.rectangle 命令在 OpenCV 中创建矩形:
Cv2.rectangle(img, pt1, pt2, color, thickness=1, lineType=cv2.LINE_8, shift=0)
参数:
-
Img: 绘制的图像。
-
Pt1:矩形的左上角点: 矩形的左上角点。格式为 tuple (x,y)。
-
Pt2: 矩形的右下角点: 矩形的右下角点。格式为 tuple (x,y)。
-
Color:矩形的颜色将采用元组(B、G、R)格式。
-
厚度(Thickness): 以像素为单位的矩形边框厚度。这是一个可选参数,默认值为 1。如果矩形的厚度为负值,则会填充矩形。
-
lineType:线条类型: 线条的类型。我们将不使用此参数,因此可将其保留为默认值。
-
Shift(移位): 线条坐标中的小数位数。我们将不使用该参数,默认值为 0。
现在,根据前面的解释,让我们尝试创建这幅图像:
import numpy as np import cv2 # Create a black image img = np.zeros((600, 500, 3), dtype=np.uint8) # Draw the figure using rectangles and lines # Face cv2.rectangle(img, (150, 150), (350, 400), (242, 199, 155), thickness=-1) # Cap cv2.rectangle(img, (100, 50), (400, 150), (198, 131, 56), thickness=-1) # Mouth cv2.rectangle(img, (200, 310), (300, 330), (128, 0, 128), thickness=2) # Draw the eyes on the face as X shapes cv2.line(img, (195, 200), (212, 228), (0, 0, 0), thickness=2) cv2.line(img, (212, 200), (195, 228), (0, 0, 0), thickness=2) cv2.line(img, (288, 200), (305, 228), (0, 0, 0), thickness=2) cv2.line(img, (305, 200), (288, 228), (0, 0, 0), thickness=2) # Display the image cv2.imshow('Robo', img) cv2.waitKey(0) cv2.destroyAllWindows()
3.6 circle
cv2.circle() 函数用于在图像上绘制圆形:
cv2.circle(img, center, radius, color, thickness=1, lineType = cv2.LINE_8, shift=0)
参数
-
Img: 绘制的图像。
-
Center: 圆的中心点。格式为 tuple (x,y)。
-
Radius: 圆的半径
-
Color:圆的颜色。格式为元组(B、G、R)。
-
Thickness: 圆边框的厚度,以像素为单位: 圆边框的厚度,单位为像素。这是一个可选参数,默认值为 1。如果矩形的厚度为负值,它将填充圆。
-
lineType:线条类型: 线条的类型。我们将不使用此参数,因此可将其保留为默认值。
-
Shift(移位): 线条坐标中的小数位数。我们将不使用此参数,默认值为 0。
让我们尝试自己创建几个圆:
import numpy as np import cv2 # Create an empty canvas canvas = np.zeros((500, 500, 3), dtype=np.uint8) # Define the center point center = (250, 250) # Define the radii of the circles radius1 = 50 radius2 = 100 radius3 = 150 # Define the colors of the circles color1 = (0, 0, 255) color2 = (255, 0, 0) color3 = (0, 255, 0) # Define the thickness of the circles thickness1 = -1 thickness2 = 2 thickness3 = 10 # Draw the circles on the canvas cv2.circle(canvas, center, radius1, color1, thickness1) cv2.circle(canvas, center, radius2, color2, thickness2) cv2.circle(canvas, center, radius3, color3, thickness3) # Display the image cv2.imshow("Image", canvas) cv2.waitKey(0) cv2.destroyAllWindows()
3.7 文本(Text)
我们使用函数 cv2.putText() 为图像添加文本:
cv2.putText(img, text, org, fontFace=’cv2.FONT_HERSHEY_SIMPLEX’, fontScale=0, color=(0,0,0), thickness=1, lineType=’cv2.LINE_AA’, bottomLeftOrigin=False)
参数:
-
Img: 绘制的图像。
-
Text:文本: 要绘制的文本字符串。
-
org:文本左下角的坐标: 文本左下角的坐标。
-
fontFace:文本的字体类型。这是可选参数,默认值为 cv2.FONT_HERSHEY_SIMPLEX。
-
fontScale:字体缩放比例: 字体比例系数,乘以特定字体的基本尺寸。这是一个可选参数,默认值为 1。
-
Color(颜色):文本的颜色。将采用元组(B、G、R)格式。这是一个可选参数,默认值为 (0,0,0)。
-
厚度(Thickness): 文本中线条的粗细。这是一个可选参数,默认值为 1。如果粗细为负值,它将填充文本。
-
lineType:线条类型: 线条的类型。我们将不使用此参数,可将其保留为默认值。
-
bottomLeftOrigin: 这是一个标志,用于指示文本的位置。这是一个可选参数,默认值为 "False(假)",这将使文本位于左上角。默认值为 True 时,文本将位于左下角。
import numpy as np import cv2 # create a blank image img = np.zeros((600, 500, 3), dtype=np.uint8) # define the text to be displayed text = "Hello World!" # set the text color and position color = (255, 0, 0) pos = (50, 200) # display the text using cv2.putText() cv2.putText(img, text, pos, cv2.FONT_HERSHEY_SIMPLEX, 2, color, 3) cv2.imshow("Image with text", img) cv2.waitKey(0) cv2.destroyAllWindows()
4. 总结
本章扎实地介绍了图像的基本概念和基本操作。我们定义了像素等关键概念,并讲解了如何使用 OpenCV 库读取、显示和保存图像。此外,我们还探讨了在图像上绘制形状的实际任务,重点是矩形和圆形等基本形状。这一基础对于将来构建更复杂的图像处理应用程序非常宝贵。