背景需求:
前文实现了7张色彩纸条加上黑色边框的需求。
【教学类-55-02】20240512图层顺序挑战(四格长条纸加黑色边框、4*4、7张 、43200张去掉非7色有23040张,哈希算法快速去重剩余1221张)-CSDN博客文章浏览阅读1k次,点赞23次,收藏17次。【教学类-55-02】20240512图层顺序挑战(四格长条纸加黑色边框、4*4、7张 、43200张去掉非7色有23040张,哈希算法快速去重剩余1221张)https://blog.csdn.net/reasonsummer/article/details/138755880
问题:已知4*4格中可以出现8张颜色纸条,但需要抽取7张纸条组成任意顺序图层。一共有几种排序方式:
一、素材位置
二、预测生成的图案总数
8的阶乘=8*7*6*5*4*3*2*1=40320张
8张抽取任意抽取7张的阶乘数也是40320张
代码展示
'''
图层重叠挑战(长矩形带黑框) (抽取7) 一共有40320个不重复
作者:AI对话大师,阿夏
时间:2024年5月12日
'''
from PIL import Image, ImageDraw
import os,random
import itertools
print('--------1、制作图片-----------')
path = r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条'
folder_path = path + r'\01图片总数8的阶乘'
os.makedirs(folder_path, exist_ok=True)
# colors = ['red', 'orange','Yellow', 'green', 'blue', 'brown', 'gray','Pink',]
colors = [(255, 0, 0), (255, 165, 0), (255, 255, 0), (0, 128, 0), (0, 255, 255), (0, 0, 255), (128, 0, 128), (255, 192, 203)]
# ["大红", "橙色", "黄色", "绿色", "青色", "蓝色", "紫色", "粉红"]
from PIL import Image, ImageDraw
import os
# folder_path=r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条\jpg4万'
# 创建画布
canvas_width = 800
canvas_height = 800
canvas_color = (255, 255, 255) # 白色背景
line_color = (0, 0, 0) # 黑色线条
line_width = 3
margin = 100 # 边距
canvas = Image.new('RGB', (canvas_width, canvas_height), canvas_color)
draw = ImageDraw.Draw(canvas)
# 计算单元格大小和绘制区域
num_rows = 4
num_cols = 4
cell_size = min((canvas_width - 2 * margin) // num_cols, (canvas_height - 2 * margin) // num_rows)
start_x = (canvas_width - cell_size * num_cols) // 2
start_y = (canvas_height - cell_size * num_rows) // 2
# 绘制第一行四个单元格的长度为红色的矩形,边框为10像素的黑色
# 绘制所有单元格的矩形
# 绘制所有单元格的矩形
# for row in range(num_rows):
# for col in range(num_cols):
# x1 = start_x + col * cell_size
# y1 = start_y + row * cell_size
# x2 = x1 + cell_size
# y2 = y1 + cell_size
# draw.rectangle([(x1, y1), (x2, y2)], fill='white', outline=line_color, width=line_width)
# 4行4列8条四格纸
# 第1行
def draw_h1_rectangle(start_x, start_y, cell_size, line_color, line_width):
x1 = start_x
y1 = start_y
x2 = start_x + 4 * cell_size
y2 = start_y + 1 * cell_size
draw.rectangle([(x1, y1), (x2, y2)], fill=colors[0], outline=line_color, width=line_width)
# 第2行
def draw_h2_rectangle(start_x, start_y, cell_size, line_color, line_width):
x1 = start_x
y1 = start_y + 1 * cell_size
x2 = start_x + 4 * cell_size
y2 = start_y + 2 * cell_size
draw.rectangle([(x1, y1), (x2, y2)], fill=colors[1], outline=line_color, width=line_width)
# 第3行
def draw_h3_rectangle(start_x, start_y, cell_size, line_color, line_width):
x1 = start_x
y1 = start_y + 2 * cell_size
x2 = start_x + 4 * cell_size
y2 = start_y + 3 * cell_size
draw.rectangle([(x1, y1), (x2, y2)], fill=colors[2], outline=line_color, width=line_width)
# 第4行
def draw_h4_rectangle(start_x, start_y, cell_size, line_color, line_width):
x1 = start_x
y1 = start_y + 3 * cell_size
x2 = start_x + 4 * cell_size
y2 = start_y + 4 * cell_size
draw.rectangle([(x1, y1), (x2, y2)], fill=colors[3], outline=line_color, width=line_width)
# 第1列
def draw_l1_rectangle(start_x, start_y, cell_size, line_color, line_width):
x1 = start_x
y1 = start_y
x2 = start_x + 1 * cell_size
y2 = start_y + 4 * cell_size
draw.rectangle([(x1, y1), (x2, y2)], fill=colors[4], outline=line_color, width=line_width)
# 第2列
def draw_l2_rectangle(start_x, start_y, cell_size, line_color, line_width):
x1 = start_x + 1 * cell_size
y1 = start_y
x2 = start_x + 2 * cell_size
y2 = start_y + 4 * cell_size
draw.rectangle([(x1, y1), (x2, y2)], fill=colors[5], outline=line_color, width=line_width)
# 第3列
def draw_l3_rectangle(start_x, start_y, cell_size, line_color, line_width):
x1 = start_x + 2 * cell_size
y1 = start_y
x2 = start_x + 3 * cell_size
y2 = start_y + 4 * cell_size
draw.rectangle([(x1, y1), (x2, y2)], fill=colors[6], outline=line_color, width=line_width)
# 第4列
def draw_l4_rectangle(start_x, start_y, cell_size, line_color, line_width):
x1 = start_x + 3 * cell_size
y1 = start_y
x2 = start_x + 4 * cell_size
y2 = start_y + 4 * cell_size
draw.rectangle([(x1, y1), (x2, y2)], fill=colors[7], outline=line_color, width=line_width)
# # 将函数名称提取出来并放入列表
# function_names = ['draw_h1_rectangle','draw_h2_rectangle','draw_h3_rectangle','draw_h4_rectangle','draw_l1_rectangle','draw_l2_rectangle','draw_l3_rectangle','draw_l4_rectangle']
# # 生成所有可能的排列,是元祖()
# permutations = list(itertools.permutations(function_names))
# # 打印排列数量
# print(f"总共有 {len(permutations)} 种不同的排列。")
# # 40320 8的阶乘
import itertools
function_names = ['draw_h1_rectangle','draw_h2_rectangle','draw_h3_rectangle','draw_h4_rectangle','draw_l1_rectangle','draw_l2_rectangle','draw_l3_rectangle','draw_l4_rectangle']
# # 调用函数列表中的函数
# for draw_function in function_names:
# draw_function(start_x, start_y, cell_size, line_color, line_width)
# # # 保存图片
# # image_path = os.path.join(folder_path, f'测试.jpg')
# # canvas.save(image_path)
# # print(f'图片已保存至:{image_path}')
import itertools
#
# 生成从 8 个元素中选取 7 个元素的所有可能排列,8个互相配对40320,7个互相配对也是40320
permutations = list(itertools.permutations(function_names, 7))
# print(permutations[0:10])
# 打印排列数量
print(f"总共有 {len(permutations)} 种不同的排列。")
# 总共有 40320 种不同的排列。
n=1
# 打印所有排列
for permutation in permutations: # 因为有40万个,所以先测试前20个
# print(permutation)
# 将元组转换为函数对象列表
functions = [eval(function_name) for function_name in permutation[::-1]]
# # 打印函数对象列表,一长串文字
print(functions)
# [<function draw_triangle_2 at 0x000001A4B402F3A8>, <function draw_triangle_1 at 0x000001A4B402FB88>, <function draw_triangle_6 at 0x000001A4B4061288>, <function draw_triangle_3 at 0x000001A4B23C5AF8>, <function draw_triangle_4 at 0x000001A4B4061168>, <function draw_triangle_5 at 0x000001A4B40611F8>]
# 运行一个7元素,就打乱一次颜色,确保color【0】抽取的颜色每次都不同
# random.shuffle(colors)
# 调用函数绘制等边三角形
# 调用函数绘制矩形
for func in functions:
# 为每个函数添加缺失的参数
func(start_x, start_y, cell_size, line_color, line_width)
# 保存绘制好的图像 已知是43020所以序号是5位数
canvas.save(folder_path + fr'\{n:05d}.png')
n+=1
终端展示:
作品展示:
生成时间:
14:54-15:08 14分钟 图片总数40320张
图片分析:
1、出现一样的图片,其实是每条颜色出现的顺序不同
结果:需要去重:由于会出现这种顺序不同,但实际展示的图案结果相同的情况,因此需要去掉重复图片
2、部分图片因为图像重叠,显示的颜色数量不同
因为样例图上有7条颜色,
结论:所以这里需要删除不是7条的图案(4条、5条、6条)
思路:
1、哈希值16点坐标匹配相同样式图片。
2、去掉图片颜色数量小于9(7色+2色黑白)的图片
第一次测试:
第一步:哈希值16点坐标匹配相同样式图片。
1、图片上16个点的坐标
2、代码展示
'''
目的:检测文件内所有图片上16个坐标点的颜色,如果哈希值相同,就将图片复制到同名的哈希值文件内宝轮
作者:AI对话大师,阿夏
时间:2024年5月15日
'''
import os
import hashlib
from shutil import copyfile
from PIL import Image
path = r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条'
# 源文件夹路径
source_folder = path + r'\01图片总数8的阶乘'
# 目标文件夹路径
destination_folder = path + r'\02哈希16点颜色归类'
# 创建一个字典来存储哈希值和对应的图片路径
hash_dict = {}
# 定义获取颜色值的函数
def get_color_values(image_path, coordinates):
# 打开图片
image = Image.open(image_path)
# 存储获取到的颜色值列表
color_values = []
# 遍历坐标列表,获取对应坐标的颜色值
for coordinate in coordinates:
x, y = coordinate
# 获取指定坐标的像素值
pixel = image.getpixel((x, y))
# 提取RGB颜色值
r, g, b = pixel[:3]
# 将颜色值添加到列表中
color_values.append((r, g, b))
return color_values
# 遍历源文件夹中的每个文件
for filename in os.listdir(source_folder):
filepath = os.path.join(source_folder, filename)
# 处理图片文件
if os.path.isfile(filepath) and (filename.endswith(".jpg") or filename.endswith(".png")):
# 获取对应16个坐标的颜色值
coordinates = [
(175, 175), (325,175), (475,175), (625,175),
(175, 325), (325, 325), (475, 325), (625, 325),
(175, 475), (325, 475), (475, 475), (625, 475),
(175, 625), (325, 625), (475, 625), (625, 625)
]
color_values = get_color_values(filepath, coordinates)
# 哈希计算
hash_value = hashlib.md5(str(color_values).encode()).hexdigest() # 使用MD5算法作为哈希函数
print(hash_value)
# 将哈希值和对应的图片路径存储到字典中
if hash_value in hash_dict:
hash_dict[hash_value].append(filepath)
else:
hash_dict[hash_value] = [filepath]
# 遍历字典,复制具有相同哈希值的图片到目标文件夹
for hash_value, filepaths in hash_dict.items():
if len(filepaths) > 1:
# 创建对应的文件夹
folder_path = os.path.join(destination_folder, hash_value)
os.makedirs(folder_path, exist_ok=True)
for filepath in filepaths:
filename = os.path.basename(filepath)
destination_filepath = os.path.join(folder_path, filename)
copyfile(filepath, destination_filepath)
终端展示——每张图片的哈希值
运行时间:15:22-15:29
显示出有5750个哈希值文件夹,但是图片只有39168张,不是40320张
经过排重测试,发现原来40320张里面有5750张图片有1-12张的重复图(合计39164张)、同时有1156张图片只有单张
因此,我把哈希值16点颜色坐标代码再优化了一次,把单张图片也算上
'''
目的:检测文件内所有图片上16个坐标点的颜色,如果哈希值相同,就将图片复制到同名的哈希值文件内宝轮
作者:AI对话大师,阿夏
时间:2024年5月15日
'''
import os
import hashlib
from shutil import copyfile
from PIL import Image
path = r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条'
# 源文件夹路径
source_folder = path + r'\01图片总数8的阶乘'
# 目标文件夹路径
destination_folder = path + r'\02哈希16点颜色归类'
# 创建一个字典来存储哈希值和对应的图片路径
hash_dict = {}
# 定义获取颜色值的函数
def get_color_values(image_path, coordinates):
# 打开图片
image = Image.open(image_path)
# 存储获取到的颜色值列表
color_values = []
# 遍历坐标列表,获取对应坐标的颜色值
for coordinate in coordinates:
x, y = coordinate
# 获取指定坐标的像素值
pixel = image.getpixel((x, y))
# 提取RGB颜色值
r, g, b = pixel[:3]
# 将颜色值添加到列表中
color_values.append((r, g, b))
return color_values
# 遍历源文件夹中的每个文件
for filename in os.listdir(source_folder):
filepath = os.path.join(source_folder, filename)
# 处理图片文件
if os.path.isfile(filepath) and (filename.endswith(".jpg") or filename.endswith(".png")):
# 获取对应16个坐标的颜色值
coordinates = [
(175, 175), (325,175), (475,175), (625,175),
(175, 325), (325, 325), (475, 325), (625, 325),
(175, 475), (325, 475), (475, 475), (625, 475),
(175, 625), (325, 625), (475, 625), (625, 625)
]
color_values = get_color_values(filepath, coordinates)
# 哈希计算
hash_value = hashlib.md5(str(color_values).encode()).hexdigest() # 使用MD5算法作为哈希函数
print(hash_value)
# 将哈希值和对应的图片路径存储到字典中
if hash_value in hash_dict:
hash_dict[hash_value].append(filepath)
else:
hash_dict[hash_value] = [filepath]
# 遍历字典,复制图片到目标文件夹
for filepaths in hash_dict.values():
for filepath in filepaths:
filename = os.path.basename(filepath)
hash_value = hashlib.md5(str(get_color_values(filepath, coordinates)).encode()).hexdigest()
folder_path = os.path.join(destination_folder, hash_value)
os.makedirs(folder_path, exist_ok=True)
destination_filepath = os.path.join(folder_path, filename)
copyfile(filepath, destination_filepath)
print("图片已复制到对应的哈希值文件夹中")
终端运行
运行时间:15:47-16:01 合计40320张,包含6902个文件夹,
随机检查,发现内部每张图片都是一模一样的(检测16个坐标点颜色,正确率高)
计算每个哈希值文件里的图片数量,
'''
每个哈希值文件夹里图片的数量,最多最少
作者:AI对话大师,阿夏
时间:2024年5月15日
'''
import os
def count_images(folder_path):
image_count = 0
# 遍历文件夹中的所有文件和子文件夹
for root, dirs, files in os.walk(folder_path):
# 遍历当前文件夹中的文件
for file in files:
# 检查文件扩展名,判断是否为图片文件
if file.endswith(".jpg") or file.endswith(".png"):
image_count += 1
return image_count
folder_path = r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条\02哈希16点颜色归类' # 文件夹路径
# 存储每个文件夹的图片数量和名称
image_counts = {}
# 遍历文件夹中的每个子文件夹
for subfolder in os.listdir(folder_path):
subfolder_path = os.path.join(folder_path, subfolder)
# 计算子文件夹中的图片数量
image_count = count_images(subfolder_path)
# 存储图片数量和名称
image_counts[subfolder] = image_count
# 找到图片数量最多和最少的文件夹
max_count_folder = max(image_counts, key=image_counts.get)
min_count_folder = min(image_counts, key=image_counts.get)
print("数量最多的文件夹名称:", max_count_folder)
print("数量最少的文件夹名称:", min_count_folder)
print("最多图片数量:", image_counts[max_count_folder])
print("最少图片数量:", image_counts[min_count_folder])
三、将6902个哈希值文件夹里的第一张图片复制出来
'''
复制哈希文件名内所有的第一张图片到新的列表内
作者:AI对话大师,阿夏
时间:2024年5月15日
'''
import os
import shutil
output_folder = r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条\02哈希16点颜色归类'
new_folder = r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条\03哈希16点颜色单张'
os.makedirs(new_folder, exist_ok=True)
# 获取output_folder中的所有子文件夹
subfolders = [subfolder for subfolder in os.listdir(output_folder) if os.path.isdir(os.path.join(output_folder, subfolder))]
# 遍历每个子文件夹,复制第一张图片到新文件夹
for subfolder in subfolders:
subfolder_path = os.path.join(output_folder, subfolder)
images = os.listdir(subfolder_path)
if len(images) > 0:
# 复制第一张图片
first_image = images[0]
source_path = os.path.join(subfolder_path, first_image)
target_path = os.path.join(new_folder, first_image)
shutil.copyfile(source_path, target_path)
print("每个子文件夹的第一张图片已复制到文件夹: 03哈希16点颜色单张")
现在去掉16点坐标颜色仙童完全相同的图片后,还有6902张,
四、删除没有9色的图片
一眼就能看到这两个图片没有7色,需要剔除
代码
'''
目的:删除没有9种类颜色的色块(7色+2色黑白)
作者:AI对话大师、阿夏
时间:2024年5月14日
'''
from PIL import Image
import os
def count_colors(image_path):
image = Image.open(image_path)
colors = image.getcolors()
return len(colors)
def remove_images_with_few_colors(folder_path, min_colors=9):
image_files = [file for file in os.listdir(folder_path) if file.endswith(('.jpg', '.jpeg', '.png', '.gif'))]
for image_file in image_files:
image_path = os.path.join(folder_path, image_file)
num_colors = count_colors(image_path)
if num_colors < min_colors or num_colors >min_colors:
os.remove(image_path)
print(f"已删除颜色少于{min_colors}种的图片:{image_file}")
print("处理完成。")
# 文件夹路径
folder_path = r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条\03哈希16点颜色单张'
# 调用函数删除颜色数量少于8种的图片
remove_images_with_few_colors(folder_path, min_colors=9)
终端展示:
16:11-16:12,再次保留7色纸条图片后,生育5400张不重复的
最后有5400张!!!
第二次测试
1、先去掉非7色的图片(从40320开始删除)
'''
目的:删除没有9种类颜色的色块(7色+2色黑白)
作者:AI对话大师、阿夏
时间:2024年5月14日
'''
from PIL import Image
import os
def count_colors(image_path):
image = Image.open(image_path)
colors = image.getcolors()
return len(colors)
def remove_images_with_few_colors(folder_path, min_colors=9):
image_files = [file for file in os.listdir(folder_path) if file.endswith(('.jpg', '.jpeg', '.png', '.gif'))]
for image_file in image_files:
image_path = os.path.join(folder_path, image_file)
num_colors = count_colors(image_path)
if num_colors < min_colors or num_colors >min_colors:
os.remove(image_path)
print(f"已删除颜色少于{min_colors}种的图片:{image_file}")
print("处理完成。")
# 文件夹路径
folder_path = r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条\04图片总数8的阶乘'
# 调用函数删除颜色数量少于8种的图片
remove_images_with_few_colors(folder_path, min_colors=9)
从40320开始删除。去掉非7色的图案后,还剩23040,有17280张时4色、5色、6色
(有时间在测试一下,有多少张4色、5色、6色、7色)
2、哈希16点最表颜色检测去重复
'''
目的:检测文件内所有图片上16个坐标点的颜色,如果哈希值相同,就将图片复制到同名的哈希值文件内宝轮
作者:AI对话大师,阿夏
时间:2024年5月15日
'''
import os
import hashlib
from shutil import copyfile
from PIL import Image
path = r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条'
# 源文件夹路径
source_folder = path + r'\04图片总数8的阶乘'
# 目标文件夹路径
destination_folder = path + r'\05哈希16点颜色归类'
# 创建一个字典来存储哈希值和对应的图片路径
hash_dict = {}
# 定义获取颜色值的函数
def get_color_values(image_path, coordinates):
# 打开图片
image = Image.open(image_path)
# 存储获取到的颜色值列表
color_values = []
# 遍历坐标列表,获取对应坐标的颜色值
for coordinate in coordinates:
x, y = coordinate
# 获取指定坐标的像素值
pixel = image.getpixel((x, y))
# 提取RGB颜色值
r, g, b = pixel[:3]
# 将颜色值添加到列表中
color_values.append((r, g, b))
return color_values
# 遍历源文件夹中的每个文件
for filename in os.listdir(source_folder):
filepath = os.path.join(source_folder, filename)
# 处理图片文件
if os.path.isfile(filepath) and (filename.endswith(".jpg") or filename.endswith(".png")):
# 获取对应16个坐标的颜色值
coordinates = [
(175, 175), (325,175), (475,175), (625,175),
(175, 325), (325, 325), (475, 325), (625, 325),
(175, 475), (325, 475), (475, 475), (625, 475),
(175, 625), (325, 625), (475, 625), (625, 625)
]
color_values = get_color_values(filepath, coordinates)
# 哈希计算
hash_value = hashlib.md5(str(color_values).encode()).hexdigest() # 使用MD5算法作为哈希函数
print(hash_value)
# 将哈希值和对应的图片路径存储到字典中
if hash_value in hash_dict:
hash_dict[hash_value].append(filepath)
else:
hash_dict[hash_value] = [filepath]
# 遍历字典,复制图片到目标文件夹
for filepaths in hash_dict.values():
for filepath in filepaths:
filename = os.path.basename(filepath)
hash_value = hashlib.md5(str(get_color_values(filepath, coordinates)).encode()).hexdigest()
folder_path = os.path.join(destination_folder, hash_value)
os.makedirs(folder_path, exist_ok=True)
destination_filepath = os.path.join(folder_path, filename)
copyfile(filepath, destination_filepath)
print("图片已复制到对应的哈希值文件夹中")
终端展示:
16:30-16:43 23040张合并成了5400个文件夹
复制每个文件夹里的第一个图片
'''
复制哈希文件名内所有的第一张图片到新的列表内
作者:AI对话大师,阿夏
时间:2024年5月15日
'''
import os
import shutil
output_folder = r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条\05哈希16点颜色归类'
new_folder = r'C:\Users\jg2yXRZ\OneDrive\桌面\重叠纸条\06哈希16点颜色单张'
os.makedirs(new_folder, exist_ok=True)
# 获取output_folder中的所有子文件夹
subfolders = [subfolder for subfolder in os.listdir(output_folder) if os.path.isdir(os.path.join(output_folder, subfolder))]
# 遍历每个子文件夹,复制第一张图片到新文件夹
for subfolder in subfolders:
subfolder_path = os.path.join(output_folder, subfolder)
images = os.listdir(subfolder_path)
if len(images) > 0:
# 复制第一张图片
first_image = images[0]
source_path = os.path.join(subfolder_path, first_image)
target_path = os.path.join(new_folder, first_image)
shutil.copyfile(source_path, target_path)
print("每个子文件夹的第一张图片已复制到文件夹: 03哈希16点颜色单张")