Warning (from warnings module):
File "<__array_function__ internals>", line 180
VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
# 导入所需的库
import cv2
import numpy as np
from PIL import Image
import PySimpleGUI as sg
import io
import matplotlib.pyplot as plt
# 读取图片
image_path = sg.popup_get_file("请选择需要检查的图片")
img = cv2.imread(image_path)
# 定义多个特定颜色的范围
color_ranges = [np.array([[0, 255, 255], [0, 255, 255]], dtype=np.uint8),
np.array([[255, 0, 30], [255, 0, 30]], dtype=np.uint8)]
# 提取每个颜色的部分
masks = []
for color_range in color_ranges:
mask = cv2.inRange(img, color_range[0], color_range[1])
masks.append(mask)
# 进行轮廓检测
contours = []
for mask in masks:
cont, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # cv2.CHAIN_APPROX_NONE表明保持的原有轮廓信息完整
contours.append(cont)
# 合并contours中的所有轮廓信息,将其转换为单个numpy数组
contours = np.concatenate(contours, axis=0)
# 绘制轮廓内部分的新mask,并将每个颜色的mask进行组合
mask_new = np.zeros_like(masks[0], dtype=np.uint8)
cv2.drawContours(mask_new, contours, -1, (255, 255, 255), -1)
# 将新mask和原图进行叠加,只显示mask内的部分
res = cv2.bitwise_and(img, img, mask=mask_new)
# 将叠加后的图像编码成字符串
img_bytes = cv2.imencode('.png', res)[1].tobytes()
# 将字符串转成Image对象
image = Image.open(io.BytesIO(img_bytes))
# 转换为numpy数组并修改RGB值
image_np = np.array(image)
image_np[(image_np == [30, 0, 255]).all(axis=2)] = [255, 255, 255]
image_np[(image_np == [0, 0, 0]).all(axis=2)] = [255, 255, 255]
image_np[(image_np == [255, 0, 0]).all(axis=2)] = [255, 255, 255]
# 处理之后的图片转换为Image对象并保存
image_processed = Image.fromarray(image_np)
# 这里可以将image_processed保存到本地或者进行其他操作
img_bytes = io.BytesIO()
image_processed.save(img_bytes, format='PNG')
img = cv2.imdecode(np.frombuffer(img_bytes.getvalue(), dtype=np.uint8), 1)
# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 使用Canny算法检测边缘
edges = cv2.Canny(gray, 0, 0)
# 使用findContours函数找到轮廓
contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 遍历每个轮廓
centers = []
colors = []
for c in contours:
# 计算轮廓的矩和中心点坐标
M = cv2.moments(c)
# 如果M["m00"]为零,说明轮廓面积为零,跳过该轮廓
if M["m00"] == 0:
continue
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
centers.append((cx, cy))
# 获取中心点坐标对应的像素值,并转换为BGR格式
pixel = img[cy][cx]
pixel_bgr = tuple(map(int, pixel))
colors.append(pixel_bgr)
# 读取原图
img_ori = cv2.imread(image_path)
# 在原图上标注
alpha = 1
for i in range(len(colors)):
for j in range(i+1, len(colors)):
# 设置颜色相似度阈值,根据需要调整
threshold = 1
# 如果颜色的BGR值都在阈值范围内,则认为是相同颜色,并绘制红色线段连接中心点
if all(abs(colors[i][k] - colors[j][k]) < threshold for k in range(3)):
# 绘制起点圆点
cv2.circle(img_ori, centers[i], radius=5, color=(0, 0, 255), thickness=-1)
# 绘制终点圆点
cv2.circle(img_ori, centers[j], radius=5, color=(0, 0, 255), thickness=-1)
# 绘制线段
cv2.line(img_ori, centers[i], centers[j], (0, 0 ,255), 3)
# 将标注后的图像显示,并调整大小适应屏幕尺寸
plt.figure(figsize=(20,20))
plt.imshow(cv2.cvtColor(img_ori, cv2.COLOR_BGR2RGB))
plt.show()
在实验开始之前,让我们先来安装一下实验所需的工具包,代码如下:
数据集主要由两个文件夹构成,一个文件名为 trump ,一个为 cage 。接下来,我们利用 Python 遍历这两个文件夹,并获得所有文件的路径。
接下来,我们利用 Python 中的 OpenCV 库,对图片进行批量加载。
这里我们分别加载了两个人物的前三张图片。从上面的运行结果可以看出,每张图片大小为 256×256 。那么怎样才能一次性,将这些图片同时展示出来呢?核心思想便是将这 6 张图片拼在一起,形成一个 512×768 的图片(一行三张,一共两行)。整体的思路如下图所示:
首先让我们来实现 stack_images 函数。为了方便以后使用,我们将 stack_images 写成一个可以将图片集合转变成一张图片的函数。
终于,我们可以将 A_images ,B_images 两个图片集合进行展示了。由于 OpenCV 无法在 Notebook 上进行图片的展示。因此我们只能利用 OpenCV 读取图片,再利用 Matplotlib 进行展示。