利用OpenCV将图像进行二值化处理并可视化图像中的圆环效果

介绍

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"):打印一条信息,告知用户组合效果图已经保存到指定路径。

### 使用OpenCV实现圆环检测和识别 #### 霍夫变换原理 霍夫变换是一种基于投票机制的算法,用于在图像中检测形物体。该方法通过参数空间中的累加器来确定可能存在的心位置及其半径大小[^1]。 对于圆环结构而言,在实际应用时通常先利用边缘检测提取出边界信息,再采用改进后的霍夫变换——即霍夫梯度法来进行更精确的位置定位[^3]。 #### 图像处理步骤 为了提高后续操作效率减少误检情况的发生,建议预先对原始图象做适当调整: - **灰度化转换**:将彩色RGB图像转化为单通道灰度形式; - **高斯模糊滤波**:去除噪声干扰的同时保留重要细节特征; - **Canny算子求导数模极大值点作为候选像素集合**; 这些前期准备工作有助于增强目标形状的表现力,从而使得最终的结果更加可靠稳定[^2]。 #### Python代码实例 下面给出一段简单的Python脚本示范如何调用`cv2.HoughCircles()`完上述任务: ```python import cv2 import numpy as np # 加载测试样本文件路径下的jpg格式图片资源 img = cv2.imread('example.jpg',0) # 应用高斯平滑降噪技术降低随机因素影响程度 blur_img = cv2.GaussianBlur(img,(5,5),0) # 执行canny边缘探测获取二值化的轮廓线条分布状况 edges = cv2.Canny(blur_img, threshold1=50,threshold2=150) # 设置Hough Transform参数配置选项字典对象 circles_param_dict={ 'method':cv2.HOUGH_GRADIENT, 'dp':1, 'minDist':20, 'param1':50, 'param2':30, 'minRadius':0, 'maxRadius':0 } # 实施极坐标系下标准方程式的匹配搜索流程 detected_circles=cv2.HoughCircles(edges,**circles_param_dict) if detected_circles is not None: # 将返回结果由浮点型数组转整数列表便于绘图显示标记用途 circles=np.uint16(np.around(detected_circles)) for i in circles[0,:]: center=(i[0],i[1]) # 绘制中心红点指示符 cv2.circle(img=center,color=(0,255,0),radius=1,lineType=-1) outer_radius=i[2]+int(i[2]*0.2)# 计算外圈直径范围 inner_radius=int(outer_radius*0.7)//2 # 设定内侧边界的平均距离尺度因子 # 勾勒内外两层封闭曲线构完整的圆环图形外观效果 cv2.circle(img=img,center=center,radius=inner_radius,color=(0,255,0),thickness=2) cv2.circle(img=img,center=center,radius=outer_radius,color=(0,0,255),thickness=2) # 展现处理完毕后的可视化果界面窗口 cv2.imshow("Detected Circles", img) cv2.waitKey(0) cv2.destroyAllWindows() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值