python實現千圖成像
先放兩張效果圖:
左圖是原圖,右圖是用很多張照片縮小再拼接後做出來的馬賽克圖,有時也把這個叫做千圖成像
原理:將原圖片切割成一個一個的小塊,用一個相簿來比對和這張照片最相似的照片然後替換掉。
關於怎麼找最相似的照片,有很多種方法,可以以阮前輩的部落格作為啟發點,這裡採用的都是以顏色為基準,找到顏色最相似的照片,而未新增輪廓比較等演算法。
實現優化:這部分自己原先的打算是先讀一下相簿的照片存在一個檔案中,每次訪問這個檔案比較圖片資訊,最後再將匹配效果最好的一張照片縮小後填入相應位置,但這種演算法實現起來複雜度很高。例如,當相簿較小而原圖切割的塊數比較大時,圖片重複的次數比較多,每次縮放都要耗費大量的時間。最後看到了知乎上有位答主沒有采取這種方式,而是另闢蹊徑。先將相簿中的所有照片縮放,然後讀取這些縮放的照片的資訊,用這些資訊給照片命名。這樣做的好處是,當馬賽克塊的大小一致是不需要在比對成功後重復縮放;另外,先縮放後再讀取資訊,遍歷的畫素點要少很多,一張1920*1080的照片縮放成192*108也會在複雜度上少算99倍。
下面使用了三種演算法實現,HSV,RGB直接參考的知乎上的答主做了修改,顏色分佈直方圖演算法(顏色向量)來自阮一峰前輩提過的一種演算法。
HSV
from PIL import Image, ImageOps
from multiprocessing import Pool
#from pathos.multiprocessing import ProcessingPoll as Pool
import os
import random
from math import *
from colorsys import rgb_to_hsv
import time
import sys
#寫在最前
#馬賽克畫照片採用了三種不同的演算法,效果較好,
#效率較高的方法為HSV顏色空間模型演算法
#這部分程式碼為HSV顏色模型的實現程式碼
#一些全域性變數,在主函式中會根據需要改變
IMAGE_DB_DIR = "D:/Python/PyQt/課程設計/wallpaper"
IMAGE_DB_DIR_NEW = "D:/Python/PyQt/課程設計/New_Ku/"
REP_DIS=3
#下面兩個變數為生成的相簿的圖片的大小
#推薦值為16:9,實測效果較好值為4:3
SIZE_WIDTH_db=4
SIZE_HEIGHT_db=3
#下面兩個變數為生成的馬賽克圖片的的大小
#推薦值為1920:1080
SIZE_WIDTH=1920
SIZE_HEIGHT=1080
#進度條
NUM=0
def Cal_HSV(image):
width, height=image.size
pixels=image.load()
pixs=[]
for x in range(width):
for y in range(height):
pix=pixels[x, y]
pixs.append(pix)
H=0; S=0; V=0
count=len(pixs)
for i in range(count): #對每個畫素塊求HSV的平均值
R=pixs[i][0]
G=pixs[i][1]
B=pixs[i][2]
hsv=rgb_to_hsv(R/255, G/255, B/255)
#將RGB格式轉化為HSV格式
H+=hsv[0]
S+=hsv[1]
V+=hsv[2]
HAvg=round(H/count, 3)
SAvg=round(S/count, 3)
VAvg=round(V/count, 3)
return (HAvg, SAvg, VAvg)
def Find_Close(image, list_colors):
sim=sys.maxsize
for hsv in list_colors:
temp_sim=sqrt((image[0]-hsv[0])**2+(image[1]-hsv[1])**2+(image[2]-hsv[2])**2)
#print(temp_sim)
if temp_sim < sim:
if hsv[3] < REP_DIS:
sim=temp_sim
hsv_min=hsv
hsv[3]+=1
else:
hsv[3]=0
return tuple(hsv_min[0:3])
'''
def progress_bar(width_now, height_now):
global NUM
if height_now==0:
NUM=round((width_now+SIZE_WIDTH_db)/(SIZE_WIDTH*SIZE_HEIGHT), 3)
else:
NUM=round(((height_now-1)*SIZE_WIDTH+width_now+SIZE_WIDTH_db)/(SIZE_WIDTH*SIZE_HEIGHT), 3)
return NUM
'''
def Make_Mosaic(image, color_list):
print("生成圖片中...")
print("生成的馬賽克圖片大小為", image.size)
width, height=image.size
count_images=round((width * height)/(SIZE_WIDTH_db*SIZE_HEIGHT_db))
#計算總共需要的馬賽克塊的數目,為了配合進度條使用
#images
new_image=Image.new('RGB', image.size)#, (255, 255, 255))
for y1 in range(0, height, SIZE_HEIGHT_db):
for x1 in range(0, width, SIZE_WIDTH_db):
y2=y1+SIZE_HEIGHT_db
x2=x1+SIZE_WIDTH_db
temp_image=image.crop((x1, y1, x2, y2))
hsv=Cal_HSV(temp_image)
close_image_name=Find_Close(hsv, color_list)
#print(close_image_name)
close_image_name=IMAGE_DB_DIR_NEW+str(close_image_name)+'.jpg'
paste_image=Resize_Image(close_image_name, SIZE_WIDTH_db, SIZE_HEIGHT_db)
#paste_image=Image.open(close_image_name)
new_image.paste(paste_image, (x1, y1))
'''
progress_bar(x1, y1)
'''
return new_image
def Images_DIR():
paths=[]
for filename in os.listdir(IMAGE_DB_DIR):
image_temp_dir=IMAGE_DB_DIR+filename
paths.append((image_temp_dir, IMAGE_DB_DIR_NEW))
return paths
def Resize_Image(in_name, size_width, size_height):
image=Image.open(in_name)
image=ImageOps.fit(image, (size_width, size_height), Image.ANTIALIAS)
return image
def Convert_Image_HSV(inf):
#global IMAGE_DB_DIR_NEW
path=inf[0]
image_db_dir_new=inf[1]
image=Resize_Image(path, 160, 90)
#image=Resize_Image(path, SIZE_WIDTH_db, SIZE_HEIGHT_db)
hsv=Cal_HSV(image)
image.save(str(image_db_dir_new)+str(hsv)+".jpg")
#print(IMAGE_DB_DIR_NEW)
def Make_New_Image_DB():
print("生成配色方案中...")
paths=Images_DIR()
pool=Pool()
pool.map(Convert_Image_HSV, paths)
pool.close()
pool.join()
def Read_Image_DB():
image_db=[]
for filename in os.listdir(IMAGE_DB_DIR_NEW):
if filename=='None.jpg':
pass
else:
filename=filename.split('.jpg')[0]
filename=filename[1:-1].split(', ')
filename=list(map(float, filename))
filename.append(0)
image_db.append(filename)
return image_db
#該函式用於傳參後判斷引數是否正確
#要判斷九個變數,傳參時只傳兩個非全域性變數
def Judge_Var():
print("驗證變數中...")
if not os.path.exists(IMAGE_DB_DIR_NEW):
os.mkdir(IMAGE_DB_DIR_NEW[:-1])
#不取最後一個是為了除去"/"
#這步肯定要做異常處理,為了除錯方便先不寫
def Mosaic_Image_HSV(size_width_db,
size_height_db,
size_width,
size_height,
IMAGE_DIR,
image_db_dir,
rep_dis,
COLOR_MODIFICATION
):
#為了避免程式池不接受已改變的全域性變數,在建立新相簿成功後再改名為改變的相簿的全域性變數名
global SIZE_WIDTH_db, SIZE_HEIGHT_db, SIZE_WIDTH, SIZE_HEIGHT
global IMAGE_DB_DIR, IMAGE_DB_DIR_NEW, REP_DIS
SIZE_WIDTH_db=size_width_db; SIZE_HEIGHT_db=size_height_db
SIZE_WIDTH=size_width; SIZE_HEIGHT=size_height
IMAGE_DB_DIR=image_db_dir
IMAGE_DB_DIR_NEW=image_db_dir[0:-1]+str("DB_HSV/")
IMAGE_SAVE_DIR=("馬賽克圖_HSV"+".").join(IMAGE_DIR.split("."))
REP_DIS=rep_dis
#上述是修改七個全域性變數的值
#使用這個程式目前需要九個引數,剩餘兩個引數是開啟圖片的路徑和生成圖片的儲存路徑
#print(IMAGE_DB_DIR_NEW)
start_time=time.time()
Judge_Var()
Make_New_Image_DB()
image_turn=Resize_Image(IMAGE_DIR, SIZE_WIDTH, SIZE_HEIGHT)
list_of_images=Read_Image_DB()
image_mosaic=Make_Mosaic(image_turn, list_of_images)
#下面是未和原圖混合的,如果想要可以保留該照片
#image_mosaic.save(IMAGE_SAVE_DIR)
#image_mosaic.save("D:/Python/PyQt/課程設計/Save_img/out96.jpg")
print("hhh")
image_mosaic_blend=Image.blend(image_mosaic, image_turn, COLOR_MODIFICATION)
print("hhh")
image_mosaic_blend.save(IMAGE_SAVE_DIR) #混合後的照片的儲存
print("hhh")
end_time=time.time()
print("總耗時: %0.2f" %(end_time-start_time))
print("生成的馬賽克圖片已儲存為%s"%IMAGE_SAVE_DIR)
if __name__ =='__main__':
Mosaic_Image_HSV(size_width_db=16,
size_height_db=9,
size_width=1920,
size_height=1080,
IMAGE_DIR="F:/課設一/ptemp/“森林”中的一隻貓鼬.jpg",
image_db_dir="D:/wallpaper/",
rep_dis=3,
COLOR_MODIFICATION=0.5
)
RGB平均值
from PIL import Image, ImageOps
from multiprocessing import Pool
#from pathos.multiprocessing import ProcessingPoll as Pool
import os
import random
from math import *
import time
import sys
#寫在最前
#馬賽克畫照片採用了三種不同的演算法,效果較好,
#效率較高的方法為HSV顏色空間模型演算法
#這部分程式碼為RGB顏色模型的實現程式碼
#一些全域性變數,在主函式中會根據需要改變
IMAGE_DB_DIR = "D:/Python/PyQt/課程設計/wallpaper"
IMAGE_DB_DIR_NEW = "D:/Python/PyQt/課程設計/New_Ku/"
REP_DIS=3
#下面兩個變數為生成的相簿的圖片的大小
#推薦值為16:9,實測效果較好值為4:3
SIZE_WIDTH_db=4
SIZE_HEIGHT_db=3
#下面兩個變數為生成的馬賽克圖片的的大小
#推薦值為1920:1080
SIZE_WIDTH=1920
SIZE_HEIGHT=1080
def Cal_Color(image):
width, height=image.size
pixels=image.load()
pixs=[]
for x in range(width):
for y in range(height):
pix=pixels[x, y]
pixs.append(pix)
R=0; G=0; B=0
count=width*height
for x in range(count):
R+=pixs[x][0]
G+=pixs[x][1]
B+=pixs[x][2]
RAvg=round(R/count, 3)
GAvg=round(G/count, 3)
BAvg=round(B/count, 3)
return (RAvg, GAvg, BAvg)
def Find_Close(image, list_colors):
sim=sys.maxsize
for color in list_colors:
temp_sim=abs(image[0]-color[0])+abs(image[1]-color[1])+abs(image[2]-color[2])
if temp_sim < sim:
if color[3] < REP_DIS:
sim=temp_sim
color_min=color
color[3] +=1
else:
color[3]=0
return tuple(color_min[0:3])
def Make_Mosaic(image, color_list):
print("生成圖片中...")
print("生成的馬賽克圖片大小為", image.size)
width, height=image.size
new_image=Image.new('RGB', image.size)
for y1 in range(0, height, SIZE_HEIGHT_db):
for x1 in range(0, width, SIZE_WIDTH_db):
y2=y1+SIZE_HEIGHT_db
x2=x1+SIZE_WIDTH_db
temp_image=image.crop((x1, y1, x2, y2))
color=Cal_Color(temp_image)
close_image_name=Find_Close(color, color_list)
close_image_name=IMAGE_DB_DIR_NEW + str(close_image_name) + '.jpg'
paste_image=Image.open(close_image_name)
paste_image = Resize_Image(close_image_name, SIZE_WIDTH_db, SIZE_HEIGHT_db)
new_image.paste(paste_image, (x1, y1))
return new_image
def Images_DIR():
paths=[]
for filename in os.listdir(IMAGE_DB_DIR):
image_temp_dir=IMAGE_DB_DIR + filename
paths.append((image_temp_dir, IMAGE_DB_DIR_NEW))
return paths
def Resize_Image(in_name, size_width, size_height):
image=Image.open(in_name)
image=ImageOps.fit(image, (size_width, size_height), Image.ANTIALIAS)
return image
def Convert_Image_RGB(inf):
#global IMAGE_DB_DIR_NEW
path=inf[0]
image_db_dir_new=inf[1]
image=Resize_Image(path, 85, 85)
#image=Resize_Image(path, SIZE_WIDTH_db, SIZE_HEIGHT_db)
color=Cal_Color(image)
image.save(str(image_db_dir_new)+str(color)+".jpg")
#print(IMAGE_DB_DIR_NEW)
def Make_New_Image_DB():
print("生成配色方案中...")
paths=Images_DIR()
pool=Pool()
pool.map(Convert_Image_RGB, paths)
pool.close()
pool.join()
def Read_Image_DB():
image_db=[]
for filename in os.listdir(IMAGE_DB_DIR_NEW):
if filename == 'None.jpg':
pass
else:
filename=filename.split('.jpg')[0]
filename=filename[1:-1].split(', ')
filename=list(map(float, filename))
filename.append(0)
image_db.append(filename)
return image_db
#該函式用於傳參後判斷引數是否正確
#要判斷九個變數,傳參時只傳兩個非全域性變數
def Judge_Var():
print("驗證變數中...")
if not os.path.exists(IMAGE_DB_DIR_NEW):
os.mkdir(IMAGE_DB_DIR_NEW[:-1])
#不取最後一個是為了除去"/"
#這步肯定要做異常處理,為了除錯方便先不寫
def Mosaic_Image_RGB(size_width_db,
size_height_db,
size_width,
size_height,
IMAGE_DIR,
image_db_dir,
rep_dis,
COLOR_MODIFICATION
):
#為了避免程式池不接受已改變的全域性變數,在建立新相簿成功後再改名為改變的相簿的全域性變數名
global SIZE_WIDTH_db, SIZE_HEIGHT_db, SIZE_WIDTH, SIZE_HEIGHT
global IMAGE_DB_DIR, IMAGE_DB_DIR_NEW, REP_DIS
SIZE_WIDTH_db=size_width_db; SIZE_HEIGHT_db=size_height_db
SIZE_WIDTH=size_width; SIZE_HEIGHT=size_height
IMAGE_DB_DIR=image_db_dir
IMAGE_DB_DIR_NEW=image_db_dir[0:-1]+str("DB_RGB/")
IMAGE_SAVE_DIR=("馬賽克圖_RGB"+".").join(IMAGE_DIR.split("."))
REP_DIS=rep_dis
#上述是修改七個全域性變數的值
#使用這個程式目前需要九個引數,剩餘兩個引數是開啟圖片的路徑和生成圖片的儲存路徑
start_time=time.time()
Judge_Var()
Make_New_Image_DB()
image_turn=Resize_Image(IMAGE_DIR, SIZE_WIDTH, SIZE_HEIGHT)
list_of_images=Read_Image_DB()
image_mosaic=Make_Mosaic(image_turn, list_of_images)
#下面是未和原圖混合的,如果想要可以保留該照片
#image_mosaic.save(IMAGE_SAVE_DIR)
#image_mosaic.save("D:/Python/PyQt/課程設計/Save_img/out96.jpg")
image_mosaic_blend=Image.blend(image_mosaic, image_turn, COLOR_MODIFICATION)
image_mosaic_blend.save(IMAGE_SAVE_DIR) #混合後的照片的儲存
end_time=time.time()
print("總耗時: %0.2f" %(end_time-start_time))
print("生成的馬賽克圖片已儲存為%s"%IMAGE_SAVE_DIR)
if __name__ == '__main__':
Mosaic_Image_RGB(size_width_db=16,
size_height_db=9,
size_width=1920,
size_height=1080,
IMAGE_DIR="D:/Python/PyQt/課程設計/Save_img/out96.jpg",
image_db_dir="D:/wallpaper/",
rep_dis=3,
COLOR_MODIFICATION=0.5
)
顏色向量法
from PIL import Image, ImageOps
import numpy
from multiprocessing import Pool
#from pathos.multiprocessing import ProcessingPoll as Pool
import os
import random
from math import *
from colorsys import rgb_to_hsv
import time
import sys
#寫在最前
#馬賽克畫照片採用了三種不同的演算法,效果較好,
#效率較高的方法為HSV顏色空間模型演算法
#這部分程式碼為HSV顏色模型的實現程式碼
#一些全域性變數,在主函式中會根據需要改變
IMAGE_DB_DIR = "D:/Python/PyQt/課程設計/wallpaper"
IMAGE_DB_DIR_NEW = "D:/Python/PyQt/課程設計/New_Ku/"
REP_DIS=3
#下面兩個變數為生成的相簿的圖片的大小
#推薦值為16:9,實測效果較好值為4:3
SIZE_WIDTH_db=4
SIZE_HEIGHT_db=3
#下面兩個變數為生成的馬賽克圖片的的大小
#推薦值為1920:1080
SIZE_WIDTH=1920
SIZE_HEIGHT=1080
#進度條
NUM=0
def Cal_Cos(list1,list2):
#print("hhh")
#print(list1,list2)
top_num=0
bottom_num1=0
bottom_num2=0
for i in range(0,27):
top_num+=int(list1[i]*list2[i])
bottom_num1+=int(list1[i])**2
bottom_num2+=int(list2[i])**2
bottom_num1=sqrt(bottom_num1)
bottom_num2=sqrt(bottom_num2)
if bottom_num1==0 or bottom_num2==0:
return 0
else:
return top_num/(bottom_num1*bottom_num2)
def Cal_Histogram(image):
#judge_list=[63,127,191,255]
image_vector=[0 for i in range(27)]
width, height=image.size
pixels=image.load()
pixs=[]
for x in range(width):
for y in range(height):
pix=pixels[x, y]
image_vector[int(pix[0]/86)*9+int(pix[1]/86)*3+int(pix[2]/86)*1]+=1
return tuple(image_vector[0:27])
#return (HAvg, SAvg, VAvg)
def Find_Close(image_vector, list_colors):
max_cos=0
length=len(list_colors)
#print(image_vector)
for histogram in list_colors:
#print("xxx")
#print(histogram)
temp_cos=Cal_Cos(list(image_vector), histogram)
if max_cos<temp_cos:
max_cos=temp_cos
color_histogram=histogram
histogram[27]+=1
else:
histogram[27]=0
return tuple(color_histogram[0:27])
def Make_Mosaic(image, color_list):
print("生成圖片中...")
print("生成的馬賽克圖片大小為", image.size)
width, height=image.size
count_images=round((width * height)/(SIZE_WIDTH_db*SIZE_HEIGHT_db))
#計算總共需要的馬賽克塊的數目,為了配合進度條使用
#images
new_image=Image.new('RGB', image.size)#, (255, 255, 255))
for y1 in range(0, height, SIZE_HEIGHT_db):
for x1 in range(0, width, SIZE_WIDTH_db):
y2=y1+SIZE_HEIGHT_db
x2=x1+SIZE_WIDTH_db
temp_image=image.crop((x1, y1, x2, y2))
hsv=Cal_Histogram(temp_image)
close_image_name=Find_Close(hsv, color_list)
#print(close_image_name)
close_image_name=IMAGE_DB_DIR_NEW+str(close_image_name)+'.jpg'
paste_image=Resize_Image(close_image_name, SIZE_WIDTH_db, SIZE_HEIGHT_db)
#paste_image=Image.open(close_image_name)
new_image.paste(paste_image, (x1, y1))
'''
progress_bar(x1, y1)
'''
return new_image
def Images_DIR():
paths=[]
for filename in os.listdir(IMAGE_DB_DIR):
image_temp_dir=IMAGE_DB_DIR+filename
paths.append((image_temp_dir, IMAGE_DB_DIR_NEW))
return paths
def Resize_Image(in_name, size_width, size_height):
image=Image.open(in_name)
image=ImageOps.fit(image, (size_width, size_height), Image.ANTIALIAS)
return image
def Convert_Image_Color_Histogram(inf):
#global IMAGE_DB_DIR_NEW
path=inf[0]
image_db_dir_new=inf[1]
image=Resize_Image(path, 160, 90)
#image=Resize_Image(path, SIZE_WIDTH_db, SIZE_HEIGHT_db)
color_histogram=Cal_Histogram(image)
image.save(str(image_db_dir_new)+str(color_histogram)+".jpg")
#print(IMAGE_DB_DIR_NEW)
def Make_New_Image_DB():
print("生成配色方案中...")
paths=Images_DIR()
pool=Pool()
pool.map(Convert_Image_Color_Histogram, paths)
pool.close()
pool.join()
def Read_Image_DB():
image_db=[]
for filename in os.listdir(IMAGE_DB_DIR_NEW):
if filename=='None.jpg':
pass
else:
filename=filename.split('.jpg')[0]
filename=filename[1:-1].split(', ')
filename=list(map(int, filename))
filename.append(0)
image_db.append(filename)
return image_db
#該函式用於傳參後判斷引數是否正確
#要判斷九個變數,傳參時只傳兩個非全域性變數
def Judge_Var():
print("驗證變數中...")
if not os.path.exists(IMAGE_DB_DIR_NEW):
os.mkdir(IMAGE_DB_DIR_NEW[:-1])
#不取最後一個是為了除去"/"
#這步肯定要做異常處理,為了除錯方便先不寫
def Mosaic_Image_Color_Histogram(size_width_db,
size_height_db,
size_width,
size_height,
IMAGE_DIR,
image_db_dir,
rep_dis,
COLOR_MODIFICATION
):
#為了避免程式池不接受已改變的全域性變數,在建立新相簿成功後再改名為改變的相簿的全域性變數名
global SIZE_WIDTH_db, SIZE_HEIGHT_db, SIZE_WIDTH, SIZE_HEIGHT
global IMAGE_DB_DIR, IMAGE_DB_DIR_NEW, REP_DIS
SIZE_WIDTH_db=size_width_db; SIZE_HEIGHT_db=size_height_db
SIZE_WIDTH=size_width; SIZE_HEIGHT=size_height
IMAGE_DB_DIR=image_db_dir
IMAGE_DB_DIR_NEW=image_db_dir[0:-1]+str("DB_CH/")
IMAGE_SAVE_DIR=("馬賽克圖_CH"+".").join(IMAGE_DIR.split("."))
REP_DIS=rep_dis
#上述是修改七個全域性變數的值
#使用這個程式目前需要九個引數,剩餘兩個引數是開啟圖片的路徑和生成圖片的儲存路徑
#print(IMAGE_DB_DIR_NEW)
start_time=time.time()
Judge_Var()
Make_New_Image_DB()
image_turn=Resize_Image(IMAGE_DIR, SIZE_WIDTH, SIZE_HEIGHT)
list_of_images=Read_Image_DB()
image_mosaic=Make_Mosaic(image_turn, list_of_images)
#下面是未和原圖混合的,如果想要可以保留該照片
#image_mosaic.save(IMAGE_SAVE_DIR)
#image_mosaic.save("D:/Python/PyQt/課程設計/Save_img/out96.jpg")
image_mosaic_blend=Image.blend(image_mosaic, image_turn, COLOR_MODIFICATION)
image_mosaic_blend.save(IMAGE_SAVE_DIR) #混合後的照片的儲存
end_time=time.time()
print("總耗時: %0.2f" %(end_time-start_time))
print("生成的馬賽克圖片已儲存為%s"%IMAGE_SAVE_DIR)
if __name__ =='__main__':
Mosaic_Image_Color_Histogram(size_width_db=16,
size_height_db=9,
size_width=1920,
size_height=1080,
IMAGE_DIR="F:/課設一/ptemp/“森林”中的一隻貓鼬.jpg",
image_db_dir="D:/wallpaper/",
rep_dis=3,
COLOR_MODIFICATION=0.5
)
其實這三段程式碼有很大一部分是重複的,可以直接封裝成一個類
使用:呼叫Mosaic_Image_Color_Histogram()函式,八個變數分別是馬賽克塊的長與寬,生成圖片的長與寬,圖片位置,相簿位置,相同馬賽克塊的距離,顏色修改值。
注意:這裡的image_db_dir的路徑的最後一定要加上“/”。
缺點:rep_dis(相同馬賽克塊的距離)這裡運算的方法是不對的,還有COLOR_MODIFICATION(顏色修改)這個變數是因為當馬賽克塊比較大時,不比較輪廓的缺點就暴露出來了,生成圖片的效果很糟糕,所以就在生成照片後與原照片進行一次合併,這樣的效果就會好很多。
參考:
http://www.ruanyifeng.com/blog/2011/07/principle_of_similar_image_search.html
http://www.ruanyifeng.com/blog/2013/03/similar_image_search_part_ii.html
感謝:
阮一峰:
http://www.ruanyifeng.com/blog/(部落格地址)
知乎答主:
今晚的風兒很喧囂(知乎ID),
https://www.zhihu.com/people/CatchFish/activities(知乎地址)
https://www.zhihu.com/question/27621722/answer/269085034(文章地址)
顯示卡君hy(知乎ID),
https://www.zhihu.com/people/xian-qia-jun-hy/activities(知乎地址),
https://link.zhihu.com/?target=http%3A//xianka.luobotou.org/%3Fp%3D54(文章地址)
相關文章
- 幻影成像的實現原理是怎樣的?
- 幻影成像的實現方式和應用領域
- python實現橫向拼接圖片Python
- python 三種方式實現截圖Python
- Python 實現圖靈微信機器人Python圖靈機器人
- 【python--爬蟲】千圖網高清背景圖片爬蟲Python爬蟲
- Python網頁截圖/螢幕截圖/截長圖如何實現?Python網頁
- 使用python matplotlib實現動圖繪製Python
- Python 萌新 - 實現 Markdown 圖片下載器Python
- 用Python實現圖片的清晰掃描Python
- Python 實現圖書超期提醒小幫手Python
- python資料結構之圖的實現Python資料結構
- 電鏡的成像原理-透射電鏡成像原理1
- 電鏡的成像原理-透射電鏡成像原理2
- 大話成像之數字成像系統培訓
- 【實戰】通過Python實現疫情地圖視覺化Python地圖視覺化
- Python實現雙X軸雙Y軸繪圖Python繪圖
- Q-Q圖原理詳解及Python實現Python
- 相機成像原理
- 多主攝計算影像實現了全焦段融合,具有出色的成像能力。
- 千相千面圖形語法
- python flask紅圖(Redprint)實現以及自動註冊到藍圖PythonFlask
- 電鏡的成像原理-冷凍電鏡成像技術1
- 使用Python爬蟲實現自動下載圖片Python爬蟲
- 【Python案例】用某度AI介面實現摳圖並改圖片底色PythonAI
- 空中成像技術概述
- 小提琴圖的繪製方法:Python matplotlib實現Python
- icnbat(圖示打仗)破解實戰 (12千字)BAT
- 水波圖實現原理
- 繪圖的實現繪圖
- js實現視訊截圖,視訊批量截圖,canvas實現JSCanvas
- canvas實現的千輪眼程式碼例項Canvas
- 別再自己摳圖了,Python用5行程式碼實現批量摳圖Python行程
- 妙招:使用Python實現圖片在人臉識別並顯示Python
- python實現一個無介面的小型圖書管理系統Python
- 基於Python PIL實現簡單圖片格式轉化器Python
- python實現超級瑪麗小遊戲(動圖演示+原始碼分享)Python遊戲原始碼
- 【Shell】使用指令碼實現數以千計HTML檔案中圖片名小寫轉換需求指令碼HTML