介绍
开源计算机视觉库(OpenCV)提供了免费的编程工具,用于处理视觉输入,如图像或视频文件。它包含许多现成的函数,可以通过不同的编程语言访问。我在这里发布的示例使用的是Python。因此,如果您想理解代码,至少需要具备基本的Python和NumPy知识。
像素如何构成图像
在大多数情况下,计算机图像是基于RGB(在OpenCV中为BGR)模型。这意味着像素颜色是Red、Green和Blue三个成分的混合。还有其他模型(例如Hue、Saturation和Value)以及矢量图形(SVG或PDF),但我在这里不打算解释它们。
计算机上的图像可以被描述为一个像素集合,其中包含颜色信息。从更技术的角度来看,图像是一个三维数组(或具有三个颜色通道的像素矩阵),前两个维度决定图像的大小(高度和宽度),第三个维度包含红色、绿色和蓝色的值(每种颜色的值范围在0到255之间)。如果图像只有一个颜色通道(8位图像),则它是一个灰度图像,灰度值范围从0(黑色)到255(白色)。 图1 说明了这一点。
图1:图像被表示为数组。右侧是一个彩色图像的示例,其中红色、绿色和蓝色的值范围从0到255(0,0,255是蓝色)。左侧是一个灰度图像,具有一个通道,表示不同的灰度。
将颜色信息转化为不同大小的点
上述讨论的原理可以应用于使用NumPy和OpenCV库在Python中进行图像编辑。在这个例子中,我使用循环来处理表示为NumPy数组的图像。循环并不是遍历图像中的每个像素,而是以固定间隔跳过像素(例如,它处理每第10个像素)。在每个处理过的像素处的灰度值用于确定点的大小(例如,灰度值为100对应于特定的点大小)。然后,这些点被绘制在原始图像的空副本上,使用来自原始图像的颜色信息。总之,我创建了一个图像副本,其中根据原始图像的颜色信息放置了不同大小的点(见图2)。
图2:绘制一个点时使用原始图像中像素的颜色信息。为了确定点的大小,使用原始图像的灰度版本。
下面是代码,可能的结果如图3所示。
import numpy as np
import cv2
# 加载图像;在不提供路径信息时,图像必须位于工作目录中
img = cv2.imread('FlowerPower.jpg',cv2.IMREAD_UNCHANGED)
# 显示图像数组的维度
print(img.shape)
# 选择整个图像的缩放因子;以便在计算机屏幕上显示
resizing = .2
# 将原始图像转换为灰度图像
img_grey = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 创建原始图像的副本
img_output = img.copy()
# 通过将每个像素的颜色设置为白色(255,255, 255)来制作白色画布
# [:,:]覆盖数组的第一和第二维的所有值
img_output[:,:] = [255,255,255] # 或者用黑色 [0,0,0] 或其他颜色
# 循环遍历图像的设置
step_width = 40 # 循环的步长;这里是每隔30个像素
# -1 填充绘制到输出图像上的圆;正值定义
# 圆的线条粗细
thickness = -1
perc = .2 # 在输出图像上绘制圆/点的大小因子
# 对数组的前两个维度(宽度和高度)进行循环
# step_width 定义包含哪些像素
for i in range(2, img.shape[0] - step_width, step_width):
for u in range(2, img.shape[1] - step_width, step_width):
# 半径(点的大小)基于原始图像灰度版本的值
# 在当前索引处的像素;例如,i = 10, u = 30 可能有 123
# perc 变量修改点的大小
radius = int((255-img_grey[i,u])*perc) +1
if radius <= 0:
radius +=1
# 从原始图像的 [i,u] 位置获取颜色
# 例如,i = 10, u = 30 可能有 [123,0,61]
color = img[i,u].astype(int).tolist()
# 使用基于灰度值的点大小和原始图像的颜色在输出图像上绘制一个圆
cv2.circle(img_output, (u,i), radius, color, thickness)
# 调整图像大小,以便它们不会太大而无法在计算机屏幕上显示
# 基于页面顶部定义的调整大小变量
img_size = img.shape
img_sm = cv2.resize(img,(int(img_size[1]*resizing), int(img_size[0]
* resizing)), interpolation = cv2.INTER_CUBIC)
# 打开一个窗口显示原始图像
cv2.imshow("Original", img_sm)
img_output_sm = cv2.resize(img_output,(int(img_size[1]*resizing), int(img_size[0]*
resizing)), interpolation = cv2.INTER_CUBIC)
# 显示点状图像
cv2.imshow("Dotted Image", img_output_sm)
# 等待按键事件;按下 q 或 ESC 将关闭窗口并结束程序
# 按下 s 时,点状图像将保存在工作目录中
k = cv2.waitKey(0)
if k == ord("q") or k == 27:
cv2.destroyAllWindows()
elif k == ord("s"):
cv2.imwrite("Dotted_Image.jpg", img_output)
cv2.destroyAllWindows()
我希望我以一种全面的方式展示了代码,并且有人可能会觉得它有用。如果你愿意,可以随意尝试一下。将圆形替换为矩形,选择不同大小的圆形,改变循环中的步幅值等等,看看会发生什么。