生成两张找不同的图片,仅有一处差异,并且这个差异要不明显且复杂,使得寻找难度增加。
为此,我们需要调整之前的代码,使得差异更为隐蔽。之前的代码中,我们直接在第二张图片中添加了一个红色多边形,可能过于显眼。
改进思路
-
差异的隐蔽性:
- 颜色相近:将差异部分的颜色设置为与背景或周围图形颜色相近,避免过于明显。
- 形状变化:对某个已有的复杂形状进行微小的修改,而不是新增一个形状。
- 位置微调:稍微移动某个形状的位置,使其与原图略有不同。
-
复杂性:
- 增加背景复杂度:绘制更多的随机图形,增加背景的复杂程度。
- 使用复杂的图案:绘制包含细节的图形,如带有纹理的多边形。
实现方案
-
选择一个随机的形状进行修改:在绘制图形时,记录所有绘制的图形参数(如形状类型、位置、大小、颜色等),然后随机选择其中一个,对其进行微小的修改,生成差异。
-
差异的类型:
-
颜色变化:将选定形状的颜色稍微调整,使其与原颜色接近,但有细微差别。
-
形状变化:改变形状的大小、角度,或者对多边形的某个顶点进行微调。
-
-
确保差异不明显:差异的修改应在视觉上不易察觉,需要仔细观察才能发现。
修改后的代码
以下是修改后的完整代码,包含详细注释:
python
from PIL import Image, ImageDraw
import random
# 设置图片尺寸
width, height = 800, 600
# 创建空白图片
image1 = Image.new('RGB', (width, height), 'white')
image2 = image1.copy()
# 创建绘图对象
draw1 = ImageDraw.Draw(image1)
draw2 = ImageDraw.Draw(image2)
# 随机种子,保证每次生成的图形相同(可选)
random.seed(42)
# 用于记录所有绘制的形状信息
shapes = []
# 绘制复杂的图形和形状
for _ in range(300):
# 随机选择形状类型
shape_type = random.choice(['rectangle', 'ellipse', 'polygon', 'line'])
# 随机颜色
color = tuple(random.choices(range(256), k=3))
# 随机位置和大小
x1, y1 = random.randint(0, width), random.randint(0, height)
x2, y2 = random.randint(0, width), random.randint(0, height)
# 保证坐标顺序正确
x0, x1 = min(x1, x2), max(x1, x2)
y0, y1 = min(y1, y2), max(y1, y2)
bbox = [x0, y0, x1, y1]
# 随机多边形顶点
num_points = random.randint(3, 8)
points = [(random.randint(0, width), random.randint(0, height)) for _ in range(num_points)]
# 线条宽度
line_width = random.randint(1, 5)
# 绘制形状并记录
shape_info = {'type': shape_type, 'color': color, 'bbox': bbox, 'points': points, 'line_width': line_width}
if shape_type == 'rectangle':
draw1.rectangle(bbox, fill=color)
draw2.rectangle(bbox, fill=color)
elif shape_type == 'ellipse':
draw1.ellipse(bbox, fill=color)
draw2.ellipse(bbox, fill=color)
elif shape_type == 'polygon':
draw1.polygon(points, fill=color)
draw2.polygon(points, fill=color)
elif shape_type == 'line':
draw1.line([x0, y0, x1, y1], fill=color, width=line_width)
draw2.line([x0, y0, x1, y1], fill=color, width=line_width)
# 记录形状信息
shapes.append(shape_info)
# 在 shapes 中随机选择一个形状进行微小的修改,作为差异
diff_shape = random.choice(shapes)
# 在第二张图片上对该形状进行微小的修改
if diff_shape['type'] == 'rectangle' or diff_shape['type'] == 'ellipse':
# 微调颜色
new_color = tuple((c + random.randint(-30, 30)) % 256 for c in diff_shape['color'])
# 在 image2 上重新绘制该形状,使用新的颜色
if diff_shape['type'] == 'rectangle':
draw2.rectangle(diff_shape['bbox'], fill=new_color)
elif diff_shape['type'] == 'ellipse':
draw2.ellipse(diff_shape['bbox'], fill=new_color)
elif diff_shape['type'] == 'polygon':
# 微调一个顶点的位置
idx = random.randint(0, len(diff_shape['points']) - 1)
original_point = diff_shape['points'][idx]
new_point = (original_point[0] + random.randint(-15, 15), original_point[1] + random.randint(-15, 15))
new_points = diff_shape['points'].copy()
new_points[idx] = new_point
# 在 image2 上重新绘制该多边形,使用新的顶点
draw2.polygon(new_points, fill=diff_shape['color'])
elif diff_shape['type'] == 'line':
# 微调线条的终点
x0, y0, x1, y1 = diff_shape['bbox']
x1_new = x1 + random.randint(-15, 15)
y1_new = y1 + random.randint(-15, 15)
draw2.line([x0, y0, x1_new, y1_new], fill=diff_shape['color'], width=diff_shape['line_width'])
# 保存图片
image1.save('find_difference_image1.png')
image2.save('find_difference_image2.png')
print("两张找不同的图片已生成:find_difference_image1.png 和 find_difference_image2.png")
print("提示:两张图片仅有一处细微差异,快来找找看吧!")
代码详解
-
记录绘制的形状信息
- 使用列表
shapes
保存每个绘制的形状的信息,包括类型、颜色、位置等。
pythonshapes = []
- 使用列表
-
在绘制形状时,保存形状信息
- 每次绘制形状后,将相关信息保存到
shapes
列表中。
pythonshape_info = {'type': shape_type, 'color': color, 'bbox': bbox, 'points': points, 'line_width': line_width} # ... shapes.append(shape_info)
- 每次绘制形状后,将相关信息保存到
-
随机选择一个形状进行微调
- 从
shapes
列表中随机选择一个形状,作为差异的目标。
pythondiff_shape = random.choice(shapes)
- 从
-
根据形状类型进行微调
-
矩形和椭圆:微调颜色,使其与原颜色接近但略有不同。
pythonnew_color = tuple((c + random.randint(-30, 30)) % 256 for c in diff_shape['color']) # 重新绘制该形状,使用新的颜色
-
多边形:微调一个顶点的位置。
pythonidx = random.randint(0, len(diff_shape['points']) - 1) original_point = diff_shape['points'][idx] new_point = (original_point[0] + random.randint(-15, 15), original_point[1] + random.randint(-15, 15)) new_points = diff_shape['points'].copy() new_points[idx] = new_point # 重新绘制该多边形,使用新的顶点
-
线条:微调线条的终点位置。
pythonx0, y0, x1, y1 = diff_shape['bbox'] x1_new = x1 + random.randint(-15, 15) y1_new = y1 + random.randint(-15, 15) draw2.line([x0, y0, x1_new, y1_new], fill=diff_shape['color'], width=diff_shape['line_width'])
-
-
在第二张图片上应用微调
- 使用
draw2
在image2
上重新绘制被修改的形状。
- 使用
-
保存和提示
- 保存两张图片,并提示用户有一处细微差异。
运行结果
执行代码后,您将获得两张图片:
find_difference_image1.png
:原始图片。find_difference_image2.png
:仅有一处细微差异的图片。
提示:差异可能是某个形状的颜色略有不同,或某个多边形的顶点位置有细微变化,需要仔细观察才能发现。
调整参数以增加难度
-
微调幅度
-
颜色变化范围:
random.randint(-30, 30)
,可以调整为更小的范围,如(-15, 15)
,使差异更不明显。 -
位置变化范围:
random.randint(-15, 15)
,可以减小范围,使形状的变化更细微。
-
-
增加图形数量
- 将
range(300)
中的数字增加,如range(500)
,使背景更加复杂。
- 将
-
形状复杂度
-
增加多边形的顶点数量,使形状更复杂。
pythonnum_points = random.randint(5, 10)
-
注意事项
-
随机性
-
为了保证每次生成的图片一致,便于调试,我们设置了随机种子
random.seed(42)
。 -
如果希望每次生成不同的图片,可以移除或更改随机种子。
-
-
依赖库
-
请确保已安装
Pillow
库:bashpip install Pillow
-
-
可能的差异类型
-
颜色变化:颜色的RGB值变化范围在
(-30, 30)
内,视觉上不易察觉。 -
位置变化:形状的位置微调在
(-15, 15)
像素内,变化较小。
-
验证差异
-
人工查找
- 打开两张图片,仔细对比,尝试找出差异所在。
-
使用差异检测算法
- 可以使用之前提供的差异检测代码,检测并标记出差异区域。
示例:使用差异检测算法
python
import cv2
import numpy as np
# 读取两张图片
img1_color = cv2.imread('find_difference_image1.png')
img2_color = cv2.imread('find_difference_image2.png')
# 转换为灰度图
img1_gray = cv2.cvtColor(img1_color, cv2.COLOR_BGR2GRAY)
img2_gray = cv2.cvtColor(img2_color, cv2.COLOR_BGR2GRAY)
# 计算差异
diff = cv2.absdiff(img1_gray, img2_gray)
# 阈值处理
_, thresh = cv2.threshold(diff, 15, 255, cv2.THRESH_BINARY)
# 使用形态学操作去除噪声
kernel = np.ones((3, 3), np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# 查找差异区域的轮廓
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 绘制差异区域
for contour in contours:
area = cv2.contourArea(contour)
if area > 50:
x, y, w, h = cv2.boundingRect(contour)
cv2.rectangle(img2_color, (x, y), (x + w, y + h), (0, 0, 255), 2)
# 显示结果
cv2.imshow('Differences', img2_color)
cv2.waitKey(0)
cv2.destroyAllWindows()
总结
通过上述修改,我们生成了两张复杂的"找不同"图片,只有一处细微的差异,并且这个差异不容易被发现。这样可以满足您对复杂度和隐蔽性的要求。
如果您希望进一步调整差异的难度或类型,可以根据需要修改代码中的参数和逻辑。
如有任何问题或需要进一步的帮助,请随时告诉我!