好的,让我们看看这是否适合您。如果我正确理解了您想要实现的目标,那么这是我的(初学者)解决方案。
本质上,我在 3D 数组中获取图像,找到图片中所有唯一的颜色,并将它们替换为整数(函数:arr_to_int
)。然后找到所有具有该函数的簇find_clusters
。使用新颜色创建一个字典,其颜色数量与簇的数量相同(因此每个簇的每个整数都会再次替换为颜色)。
最后再次将所有 int 替换为颜色并保存图片。
这是我用来开始的图像:
这就是我作为输出得到的新图片:
如果您更改如何将它们集群应用到您想要使用的特定颜色的过程,我想我非常接近您想要实现的目标(希望如此:))
import numpy as np
import cv2
from scipy import ndimage
# array of GBR colors to single int
def arr_to_int(arr, col_mask):
out = np.ndarray(shape=arr.shape[:2], dtype=int)
out[:,:] = -1
for rgb, idx in col_mask.items():
out[(arr==rgb).all(2)] = idx
return out
# find unique clusters of identical RGB codes
def find_clusters(array):
clustered = np.empty_like(array)
unique_vals = np.unique(array)
cluster_count = 0
for val in unique_vals:
labelling, label_count = ndimage.label(array == val)
for k in range(1, label_count + 1):
clustered[labelling == k] = cluster_count
cluster_count += 1
return clustered, cluster_count
# Load image
im = cv2.imread("prov_test.png")
#im = cv2.resize(im, (2, 3)) #resize for debugging
#print('original image: \n', im, '\n')
#find all unique colors in image (cv2 presents in BGR format!!!)
unique_col_BGR = list(set(tuple(v) for m2d in im for v in m2d))
print('unique values: ', unique_col_BGR, '\n')
#create dict with GBR_colors as keys and unique integers as value
mask_GBR_int = {color:idx for idx,color in enumerate(unique_col_BGR)}
print('mask dict: ', mask_GBR_int, '\n')
#change all color values in im to a single int (mask)
im_with_ints = arr_to_int(im, mask_GBR_int)
#print('pic with mask values: \n', im_with_ints, '\n')
# due to replacing array of 3 values to a single int, new array has one dimension less
print('orig pic resized shape', im.shape)
print('Mask int pic shape', im_with_ints.shape, '\n')
clusters, cluster_count = find_clusters(im_with_ints)
print(f'Found {cluster_count} clusters', '\n')
#print(clusters)
#create dict with length equal to number of clusters and choose color of list_of_colors (random from the internet)
list_of_colors = [[192,192,192],[128,128,128],[128,0,0],[128,128,0],[0,128,0],[128,0,128],[0,128,128],[0,0,128],[255,0,0],[0,255,0],[0,0,255],[255,255,0],[0,255,255],[255,0,255]]
new_color_dict = {idx:val for idx,val in enumerate(list_of_colors[:cluster_count])}
print('new_color_dict: ', new_color_dict,'\n')
#change arr with int to colors again
res = np.array([*new_color_dict.values()])[clusters]
#print('image array with new colors: \n', res)
cv2.imwrite("prov_test_output.png", res)
Output:
unique values: [(0, 255, 0), (255, 0, 0), (0, 0, 255), (0, 255, 255)]
mask dict: {(0, 255, 0): 0, (255, 0, 0): 1, (0, 0, 255): 2, (0, 255, 255): 3}
orig pic resized shape (100, 100, 3)
Mask int pic shape (100, 100)
Found 9 clusters
new_color_dict: {0: [192, 192, 192], 1: [128, 128, 128], 2: [128, 0, 0], 3: [128, 128, 0], 4: [0, 128, 0], 5: [128, 0, 128], 6: [0, 128, 128], 7: [0, 0, 128], 8: [255, 0, 0]}