介绍
OpenCV(Open Source Computer Vision Library)是一个开源计算机视觉库,广泛用于图像和视频处理。它提供了丰富的功能,包括图像处理、特征检测、几何变换、视频分析以及机器学习等。由于其高效性、跨平台性和开源性质,OpenCV被广泛应用于计算机视觉领域,尤其在自动驾驶、安防监控和医疗影像等领域有着重要应用。
所有代码
import cv2
import numpy as np
import matplotlib
matplotlib.use('Agg') # Use 'Agg' backend for non-interactive plotting
import matplotlib.pyplot as plt
# ========== 1. 读取图像 ==========
image_path = "C:\\Users\\Lenovo\\Desktop\\coin.jpg"
img = cv2.imread(image_path)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# ========== 2. 二值化 ==========
_, img_binary = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
# ========== 3. 提取圆环 ==========
# 查找轮廓
_, binary_for_contour = cv2.threshold(img_gray, 100, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
contours, _ = cv2.findContours(binary_for_contour, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
# 找最大轮廓
largest_contour = max(contours, key=cv2.contourArea)
(x, y), radius = cv2.minEnclosingCircle(largest_contour)
center = (int(x), int(y))
radius = int(radius)
padding = 50
new_w = max(img.shape[1], 2 * radius + 2 * padding)
new_h = max(img.shape[0], 2 * radius + 2 * padding)
center_x = new_w // 2
center_y = new_h // 2
# 创建白色圆
full_circle = np.zeros((new_h, new_w), dtype=np.uint8)
cv2.circle(full_circle, (center_x, center_y), radius, 255, -1)
# 蚀去内部形成圆环
kernel_erode = np.ones((15, 15), np.uint8)
inner_circle = cv2.erode(full_circle, kernel_erode, iterations=1)
ring = cv2.subtract(full_circle, inner_circle)
# ========== 4. 创建红色圆环 ==========
# 创建一个全黑的彩色背景
red_ring_img = np.zeros((new_h, new_w, 3), dtype=np.uint8)
# 绘制一个红色的实心圆
cv2.circle(red_ring_img, (center_x, center_y), radius, (0, 0, 255), -1) # BGR format: (Blue, Green, Red)
# 绘制一个稍小的黑色实心圆,形成圆环
inner_radius = radius - 15 # 调整这个值来控制圆环的厚度
if inner_radius > 0:
cv2.circle(red_ring_img, (center_x, center_y), inner_radius, (0, 0, 0), -1)
else:
print("未找到轮廓")
ring = np.zeros_like(img_gray)
red_ring_img = np.zeros((img_gray.shape[0], img_gray.shape[1], 3), dtype=np.uint8)
# ========== 5. 可视化输出 ==========
plt.figure(figsize=(16, 8)) # 调整 figsize 以容纳更多子图
# 原图
plt.subplot(1, 4, 1) # 1行4列的第一个子图
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title("Original Image")
plt.axis('off')
# 二值化图
plt.subplot(1, 4, 2) # 1行4列的第二个子图
plt.imshow(img_binary, cmap='gray')
plt.title("Binary Image")
plt.axis('off')
# 白色圆环图
plt.subplot(1, 4, 3) # 1行4列的第三个子图
plt.imshow(ring, cmap='gray')
plt.title("White Ring") # 标题改为 White Ring
plt.axis('off')
# 红色圆环图
plt.subplot(1, 4, 4) # 1行4列的第四个子图
plt.imshow(cv2.cvtColor(red_ring_img, cv2.COLOR_BGR2RGB)) # 红色圆环是彩色图
plt.title("Red Ring")
plt.axis('off')
plt.tight_layout()
plt.savefig("D:\\python_learning\\pythonProject\\final_image.jpg") # 保存图片而不是显示
print("组合效果图已保存到: D:\\python_learning\\pythonProject\\final_image.jpg")


图一为原图,图二为二值化处理图,图三为边界轮廓图,图四是将边界轮廓换为红色圆环的图片。
所需库
import cv2
import numpy as np
import matplotlib
所需库的安装
win+R打开cmd,逐行运行以下代码。
pip install opencv-python
pip install numpy
pip install matplotlib
代码详解
1.导入必要的库
import cv2
import numpy as np
import matplotlib
matplotlib.use('Agg') # 使用 'Agg' 后端,适用于非交互式绘图
import matplotlib.pyplot as plt
指定 Matplotlib 使用 'Agg'
后端进行图形绘制。Agg
是一个非交互式绘图后端,适用于生成图像文件(如 PNG、JPG、PDF 等),而不需要图形界面支持。使用 'Agg'
后端可以避免显示图形窗口,直接将图像保存为文件,适合批量处理图像或在服务器环境中使用。
2. 读取和预处理图像
image_path = "C:\\Users\\Lenovo\\Desktop\\coin.jpg"
img = cv2.imread(image_path) # 读取图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将图像转换为灰度图
image_path:图像文件路径。
使用 OpenCV 的 cv2.imread() 函数读取指定路径的图像,并将其存储在变量 img
中。
cv2.cvtColor()
函数将彩色图像(img
)转换为灰度图像,转换后的图像存储在 img_gray
中。
cv2.COLOR_BGR2GRAY
是转换颜色空间的标识符,表示从 BGR 转换为灰度图。
3. 二值化处理
_, img_binary = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
cv2.threshold
: 将灰度图像二值化。大于 127 的像素值设置为 255,小于等于 127 的像素值设置为 0。这里使用的是 二进制阈值(cv2.THRESH_BINARY
),生成黑白图像。
4. 提取圆环
_, binary_for_contour = cv2.threshold(img_gray, 100, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
contours, _ = cv2.findContours(binary_for_contour, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.threshold():用于对图像进行阈值处理,将图像转换为二值图像(黑白图像)。返回两个值:阈值和二值化后的图像。
img_gray:输入的灰度图像。
100:设定的阈值。如果像素值大于 100,则设置为 255(白色);如果小于等于 100,则设置为 0(黑色)。
255:二值化后大于阈值的像素设置为的值(255 即白色)。
cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU:这两个参数的组合:
cv2.THRESH_BINARY_INV:进行反向二值化(黑白反转),即大于阈值的像素设置为 0,小于阈值的设置为 255。
cv2.THRESH_OTSU:使用 OTSU 方法自动计算最佳的阈值。
这一步的目的是得到一个反向二值化图像 binary_for_contour,该图像用于后续的轮廓提取。
if contours:
largest_contour = max(contours, key=cv2.contourArea) # 找到最大轮廓
(x, y), radius = cv2.minEnclosingCircle(largest_contour) # 拟合最小圆形
center = (int(x), int(y)) # 圆心
radius = int(radius) # 圆的半径
max(contours, key=cv2.contourArea)
:选择轮廓中面积最大的一个。cv2.minEnclosingCircle()
:为该最大轮廓拟合一个最小圆形,返回圆心坐标和半径。
center
和 radius
:存储圆心坐标和圆的半径,用于后续的图形绘制或分析。
padding = 50
new_w = max(img.shape[1], 2 * radius + 2 * padding) # 新图像的宽度,确保能容纳圆
new_h = max(img.shape[0], 2 * radius + 2 * padding) # 新图像的高度
center_x = new_w // 2 # 新图像的圆心位置
center_y = new_h // 2
padding: 增加的边距,确保圆不会被裁剪掉。
计算 new_w 和 new_h 来确定生成的新图像尺寸,使得图像能够容纳圆环。
# 创建白色圆
full_circle = np.zeros((new_h, new_w), dtype=np.uint8)
cv2.circle(full_circle, (center_x, center_y), radius, 255, -1)
创建一个白色圆,绘制在一个新的黑色背景图像上。
np.zeros((new_h, new_w), dtype=np.uint8)
:创建一个新的黑色图像(矩阵),大小为 (new_h, new_w)
,并且每个像素值初始化为 0(黑色)。
cv2.circle()
:在图像 full_circle
上绘制一个白色圆形。
# 蚀去内部形成圆环
kernel_erode = np.ones((15, 15), np.uint8)
inner_circle = cv2.erode(full_circle, kernel_erode, iterations=1)
ring = cv2.subtract(full_circle, inner_circle)
kernel_erode:创建一个 15x15 的结构元素矩阵,用于腐蚀操作。
cv2.erode():通过腐蚀操作减少图像中圆的大小,得到一个比原圆小的内圆。
cv2.subtract():通过图像减法操作,计算原圆和内圆之间的差异,从而得到一个圆环。
5. 创建红色圆环
red_ring_img = np.zeros((new_h, new_w, 3), dtype=np.uint8)
cv2.circle(red_ring_img, (center_x, center_y), radius, (0, 0, 255), -1)
同理,创建一个全黑的彩色图像(3通道),并绘制一个红色实心圆(BGR格式中红色是 (0, 0, 255)
)。
inner_radius = radius - 15 # 调整值控制圆环的厚度
if inner_radius > 0:
cv2.circle(red_ring_img, (center_x, center_y), inner_radius, (0, 0, 0), -1)
调整圆环的厚度,并在图像中绘制一个黑色的内圆,以形成圆环的效果。
radius
:之前计算的圆的半径,这个半径表示外圆的大小。
inner_radius = radius - 15
:通过将 radius
减去 15,计算出内圆的半径。这个减去的 15 值就是控制圆环厚度的因素。减去的数值越大,圆环的厚度越小,反之,厚度越大。
if inner_radius > 0:
:判断计算得到的 inner_radius
是否大于 0。如果 inner_radius
为负值或零,不会执行后面的绘制操作。
cv2.circle()在内部画一个黑色的圆。
6. 可视化结果并保存
plt.figure(figsize=(16, 8)) # 设置图像大小
# 原图
plt.subplot(1, 4, 1) # 原图子图
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 将BGR图像转为RGB以便显示
plt.title("Original Image")
plt.axis('off')
# 二值化图
plt.subplot(1, 4, 2) # 二值化图子图
plt.imshow(img_binary, cmap='gray')
plt.title("Binary Image")
plt.axis('off')
# 白色圆环图
plt.subplot(1, 4, 3) # 白色圆环图子图
plt.imshow(ring, cmap='gray')
plt.title("White Ring")
plt.axis('off')
# 红色圆环图
plt.subplot(1, 4, 4) # 红色圆环图子图
plt.imshow(cv2.cvtColor(red_ring_img, cv2.COLOR_BGR2RGB)) # 将BGR图像转为RGB以便显示
plt.title("Red Ring")
plt.axis('off')
plt.tight_layout() # 调整子图间距
plt.savefig("D:\\python_learning\\pythonProject\\final_image.jpg") # 保存图像
print("组合效果图已保存到: D:\\python_learning\\pythonProject\\final_image.jpg")
将四张图像并排显示在一个窗口中,并将它们保存为一个文件。
plt.figure(figsize=(16, 8))
:创建一个新的图像窗口,并设置图像的大小为宽 16 英寸,高 8 英寸。figsize
参数控制生成图像的尺寸,确保足够的空间来容纳四张子图。
plt.subplot(1, 4, 1)
:在 1 行 4 列的网格中选择第 1 个位置,表示原图将显示在第一个子图中。
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
:显示原图。由于 OpenCV 默认使用 BGR 格式读取图像,但 matplotlib
使用 RGB 格式显示图像,因此需要使用 cv2.cvtColor()
将 BGR 图像转换为 RGB 格式。
plt.title("Original Image")
:为该子图设置标题,显示 "Original Image"。
plt.title("Original Image")
:为该子图设置标题,显示 "Original Image"。
plt.tight_layout()
:自动调整子图之间的间距,确保每个子图的标题和图像不重叠,显示效果更加整齐。
plt.savefig("D:\\python_learning\\pythonProject\\final_image.jpg")
:将组合的图像保存为文件 final_image.jpg
。该文件将保存在 D:\\python_learning\\pythonProject\\
路径下。
print("组合效果图已保存到: D:\\python_learning\\pythonProject\\final_image.jpg")
:打印一条信息,告知用户组合效果图已经保存到指定路径。