在一圖勝千言的時代,沒有什么比一張圖片更有沖擊力的了,那如果一千張圖片拼接起來是什么效果呢?
別問,問就是兩字 —— 炫酷!
你有沒有想過上面的圖片是怎么實現的,難道這是用 ps 一張張拼起來的?當然,靠人工把近千張圖片按照色域一一排列,應該是不可能的。
今天我們就用 Python 做一個馬賽克圖片生成器~ 只需要 200 行 Python 代碼,就可以將任意圖片轉化為馬賽克拼圖效果,一勞永逸!拿來記錄校園生活、游戲生涯、送女朋友都最合適不過了!
ONE項目思路項目大概分為 3 個步驟:
- 計算素材庫中每張圖片的平均色
- 把目標圖片切分成平均的色塊,與素材庫圖片進行替換
- 全部替換完成后,再與原始圖像進行融合
TWO計算圖像平均值一張圖像是通過許多的像素組成的。為了生成馬賽克圖片,我們的想法是,將原有圖像的每一個小部分,使用顏色與這一小部分相似的圖像進行替換,從而生成馬賽克風格的圖像。如何計算圖片的顏色相似度?這里要引用 RGB 和 HSV 的概念。RGB 色彩空間是,由三個通道表示一幅圖像。三個通道分別為紅色 (R),綠色 (G) 和藍色 (B),通過這三種顏色的不同組合,可以形成幾乎所有的其他顏色。
但是,在自然環境下,圖像容易受自然光照、遮擋等情況的影響。也就是人眼觀察圖片會對圖片的亮度比較敏感。而 RGB 色彩空間的三個分量都與亮度密切相關,只要亮度改變,RGB 顏色的三個分量都會改變.
同時,由於人眼對於這 RGB 這三種顏色的敏感程度是不一樣的。在單色中,人眼對紅色最不敏感,藍色最敏感,所以 RGB 色彩空間是一種均勻性較差的色彩空間。
由於 RGB 色彩空間不能方便的比較顏色之間的相似度,於是我們要使用 HSV 色彩空間。HSV 色彩空間也是由三個分量組成的,分別是:
- Hue(色調)
- Saturation (飽和度)
- Value (明度)
我們會常用下圖的圓柱體來表示 HSV 色彩空間,其中:
- H 用極坐標的極角表示;
- S 用極坐標的軸的長度表示;
- V 用圓柱的高度表示;
計算圖片 HSV 值的代碼如下:
class mosaic(object):
"""定義計算圖片的平均hsv值
"""
def __init__(self, IN_DIR: str, OUT_DIR: str, SLICE_SIZE: int, REPATE: int,
OUT_SIZE: int) -> None:
self.IN_DIR = IN_DIR # 原始的圖像素材所在文件夾
self.OUT_DIR = OUT_DIR # 輸出素材的文件夾, 這些都是計算過hsv和經過resize之后的圖像
self.SLICE_SIZE = SLICE_SIZE # 圖像放縮后的大小
self.REPATE = REPATE # 同一張圖片可以重復使用的次數
self.OUT_SIZE = OUT_SIZE # 最終圖片輸出的大小
def resize_pic(self, in_name: str, size: int) -> Image:
"""轉換圖像大小
"""
img = Image.open(in_name)
img = ImageOps.fit(img, (size, size), Image.ANTIALIAS)
return img
def get_avg_color(self, img: Image) -> Tuple[float, float, float]:
"""計算圖像的平均hsv
"""
width, height = img.size
pixels = img.load()
if type(pixels) is not int:
data = [] # 存儲圖像像素的值
for x in range(width):
for y in range(height):
cpixel = pixels[x, y] # 獲得每一個像素的值
data.append(cpixel)
h = 0
s = 0
v = 0
count = 0
for x in range(len(data)):
r = data[x][0]
g = data[x][1]
b = data[x][2] # 得到一個點的GRB三色
count += 1
hsv = rgb_to_hsv(r / 255.0, g / 255.0, b / 255.0)
h += hsv[0]
s += hsv[1]
v += hsv[2]
hAvg = round(h / count, 3)
sAvg = round(s / count, 3)
vAvg = round(v / count, 3)
if count > 0: # 像素點的個數大於0
return (hAvg, sAvg, vAvg)
else:
raise IOError("讀取圖片數據失敗")
else:
raise IOError("PIL 讀取圖片數據失敗")
**以上內容出自實驗樓免費課程 —— **《Python 制作馬賽克拼合圖像》,篇幅有限,歡迎大家來實驗樓學習完整的課程代碼。
👇 點擊《Python 制作馬賽克拼合圖像》,學習完整課程。