文章目錄
- 一、通過遍歷替換
- 二、通過矩陣操作加快替換
- 三、結(jié)果對(duì)比
- 四、程序解釋
- 五、完整的測(cè)試程序
最近的對(duì)圖像數(shù)據(jù)進(jìn)行處理的時(shí)候需要將圖像中的某個(gè)顏色替換為另一個(gè)顏色,但是網(wǎng)絡(luò)上找到的方法都是通過對(duì)圖像的遍歷進(jìn)行替換,實(shí)在是太費(fèi)時(shí)了!剛開始使用時(shí)覺得CPU很快了,一張圖片應(yīng)該用不了多久,但是實(shí)際使用中耗時(shí)確實(shí)難以接受的!于是自己寫了一個(gè)替換程序加快速度,比遍歷快很多,但我覺得不是最快的,應(yīng)該有通過矩陣索引更快的處理方式,只是我自己暫時(shí)并不知道該如何實(shí)現(xiàn),如果以后能夠?qū)崿F(xiàn)會(huì)進(jìn)行更新,暫時(shí)先寫下自己暫時(shí)覺得可用的代碼。
一、通過遍歷替換
??將圖像中某個(gè)顏色替換為另一個(gè)顏色一般的做法是遍歷整個(gè)圖像,逐一替換,如下:
def
replace_color_tran
(
img
,
src_clr
,
dst_clr
)
:
''' 通過遍歷顏色替換程序
@param img: 圖像矩陣
@param src_clr: 需要替換的顏色(r,g,b)
@param dst_clr: 目標(biāo)顏色 (r,g,b)
@return 替換后的圖像矩陣
'''
img_arr
=
np
.
asarray
(
img
,
dtype
=
np
.
double
)
dst_arr
=
img_arr
.
copy
(
)
for
i
in
range
(
img_arr
.
shape
[
1
]
)
:
for
j
in
range
(
img_arr
.
shape
[
0
]
)
:
if
(
img_arr
[
j
]
[
i
]
==
src_clr
)
[
0
]
==
True
:
dst_arr
[
j
]
[
i
]
=
dst_clr
return
np
.
asarray
(
dst_arr
,
dtype
=
np
.
uint8
)
二、通過矩陣操作加快替換
??但是這樣做,處理速度是很慢的即便是現(xiàn)在CPU很快的情況下。我自己通過numpy矩陣操作將速度提升了一點(diǎn),具體做法如下:
- 將圖像的三個(gè)通道拆分開來為R,G,B三個(gè)通道
- 將三個(gè)通道的數(shù)據(jù)值進(jìn)行簡(jiǎn)單的編碼,合并為單通道矩陣;
- 將需要替換的顏色進(jìn)行同2的編碼,利用改編碼在2中得到的矩陣中得到對(duì)應(yīng)顏色的索引;
- 利用3中得到的索引將R,G,B三個(gè)通道中的對(duì)應(yīng)顏色值替換為目標(biāo)值;
- 將得到的三個(gè)通道合并為一個(gè)圖像數(shù)據(jù)。
??具體實(shí)現(xiàn)如下:
def
replace_color
(
img
,
src_clr
,
dst_clr
)
:
''' 通過矩陣操作顏色替換程序
@param img: 圖像矩陣
@param src_clr: 需要替換的顏色(r,g,b)
@param dst_clr: 目標(biāo)顏色 (r,g,b)
@return 替換后的圖像矩陣
'''
img_arr
=
np
.
asarray
(
img
,
dtype
=
np
.
double
)
r_img
=
img_arr
[
:
,
:
,
0
]
.
copy
(
)
g_img
=
img_arr
[
:
,
:
,
1
]
.
copy
(
)
b_img
=
img_arr
[
:
,
:
,
2
]
.
copy
(
)
img
=
r_img
*
256
*
256
+
g_img
*
256
+
b_img
src_color
=
src_clr
[
0
]
*
256
*
256
+
src_clr
[
1
]
*
256
+
src_clr
[
2
]
#編碼
r_img
[
img
==
src_color
]
=
dst_clr
[
0
]
g_img
[
img
==
src_color
]
=
dst_clr
[
1
]
b_img
[
img
==
src_color
]
=
dst_clr
[
2
]
dst_img
=
np
.
array
(
[
r_img
,
g_img
,
b_img
]
,
dtype
=
np
.
uint8
)
dst_img
=
dst_img
.
transpose
(
1
,
2
,
0
)
return
dst_img
三、結(jié)果對(duì)比
??先看下具體的實(shí)現(xiàn)結(jié)果,全部測(cè)試程序文末給出,(上面的圖片是原圖,下面是替換后的圖片)。
四、程序解釋
??通過如下方式編碼的原因是r,g,b三原色的數(shù)值本身是順序相關(guān)的,為了保證最后索引的一致與準(zhǔn)確性,采用將不同數(shù)值錯(cuò)位開。這里的magic number采用256是因?yàn)槿臄?shù)值的范圍是[0,255],這樣相乘可以保證數(shù)據(jù)在二進(jìn)制上的完全相互交錯(cuò)而保證該編碼是絕對(duì)正確的,當(dāng)然也可以采用其他形式的編碼或者數(shù)值選擇其他數(shù)值,我這樣選擇是為了保險(xiǎn)起見而已。
img
=
r_img
*
256
*
256
+
g_img
*
256
+
b_img
src_color
=
src_clr
[
0
]
*
256
*
256
+
src_clr
[
1
]
*
256
+
src_clr
[
2
]
#編碼
五、完整的測(cè)試程序
??完整的程序:
from
PIL
import
Image
import
os
import
numpy
as
np
import
time
def
replace_color
(
img
,
src_clr
,
dst_clr
)
:
''' 通過矩陣操作顏色替換程序
@param img: 圖像矩陣
@param src_clr: 需要替換的顏色(r,g,b)
@param dst_clr: 目標(biāo)顏色 (r,g,b)
@return 替換后的圖像矩陣
'''
img_arr
=
np
.
asarray
(
img
,
dtype
=
np
.
double
)
#分離通道
r_img
=
img_arr
[
:
,
:
,
0
]
.
copy
(
)
g_img
=
img_arr
[
:
,
:
,
1
]
.
copy
(
)
b_img
=
img_arr
[
:
,
:
,
2
]
.
copy
(
)
#編碼
img
=
r_img
*
256
*
256
+
g_img
*
256
+
b_img
src_color
=
src_clr
[
0
]
*
256
*
256
+
src_clr
[
1
]
*
256
+
src_clr
[
2
]
#索引并替換顏色
r_img
[
img
==
src_color
]
=
dst_clr
[
0
]
g_img
[
img
==
src_color
]
=
dst_clr
[
1
]
b_img
[
img
==
src_color
]
=
dst_clr
[
2
]
#合并通道
dst_img
=
np
.
array
(
[
r_img
,
g_img
,
b_img
]
,
dtype
=
np
.
uint8
)
#將數(shù)據(jù)轉(zhuǎn)換為圖像數(shù)據(jù)(h,w,c)
dst_img
=
dst_img
.
transpose
(
1
,
2
,
0
)
return
dst_img
def
replace_color_tran
(
img
,
src_clr
,
dst_clr
)
:
''' 通過遍歷顏色替換程序
@param img: 圖像矩陣
@param src_clr: 需要替換的顏色(r,g,b)
@param dst_clr: 目標(biāo)顏色 (r,g,b)
@return 替換后的圖像矩陣
'''
img_arr
=
np
.
asarray
(
img
,
dtype
=
np
.
double
)
dst_arr
=
img_arr
.
copy
(
)
for
i
in
range
(
img_arr
.
shape
[
1
]
)
:
for
j
in
range
(
img_arr
.
shape
[
0
]
)
:
if
(
img_arr
[
j
]
[
i
]
==
src_clr
)
[
0
]
==
True
:
dst_arr
[
j
]
[
i
]
=
dst_clr
return
np
.
asarray
(
dst_arr
,
dtype
=
np
.
uint8
)
img
=
'1.jpg'
img
=
Image
.
open
(
img
)
.
convert
(
'RGB'
)
res_img
=
img
.
copy
(
)
count
=
20
matrix_time
=
0
trans_time
=
0
for
i
in
range
(
count
)
:
print
(
i
)
start
=
time
.
time
(
)
dst_img
=
replace_color
(
img
,
(
8
,
10
,
51
)
,
(
255
,
0
,
0
)
)
end
=
time
.
time
(
)
matrix_time
+=
(
end
-
start
)
start
=
time
.
time
(
)
dst_img
=
replace_color_tran
(
img
,
(
8
,
10
,
51
)
,
(
255
,
0
,
0
)
)
end
=
time
.
time
(
)
trans_time
+=
(
end
-
start
)
res_img
=
dst_img
res_img
=
Image
.
fromarray
(
res_img
)
res_img
.
save
(
'2.jpg'
)
print
(
'矩陣操作花費(fèi)時(shí)間:'
,
matrix_time
/
count
)
print
(
'遍歷操作花費(fèi)時(shí)間:'
,
trans_time
/
count
)
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
