文章目錄
- 一、通過遍歷替換
- 二、通過矩陣操作加快替換
- 三、結果對比
- 四、程序解釋
- 五、完整的測試程序
最近的對圖像數據進行處理的時候需要將圖像中的某個顏色替換為另一個顏色,但是網絡上找到的方法都是通過對圖像的遍歷進行替換,實在是太費時了!剛開始使用時覺得CPU很快了,一張圖片應該用不了多久,但是實際使用中耗時確實難以接受的!于是自己寫了一個替換程序加快速度,比遍歷快很多,但我覺得不是最快的,應該有通過矩陣索引更快的處理方式,只是我自己暫時并不知道該如何實現,如果以后能夠實現會進行更新,暫時先寫下自己暫時覺得可用的代碼。
一、通過遍歷替換
??將圖像中某個顏色替換為另一個顏色一般的做法是遍歷整個圖像,逐一替換,如下:
def
replace_color_tran
(
img
,
src_clr
,
dst_clr
)
:
''' 通過遍歷顏色替換程序
@param img: 圖像矩陣
@param src_clr: 需要替換的顏色(r,g,b)
@param dst_clr: 目標顏色 (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
)
二、通過矩陣操作加快替換
??但是這樣做,處理速度是很慢的即便是現在CPU很快的情況下。我自己通過numpy矩陣操作將速度提升了一點,具體做法如下:
- 將圖像的三個通道拆分開來為R,G,B三個通道
- 將三個通道的數據值進行簡單的編碼,合并為單通道矩陣;
- 將需要替換的顏色進行同2的編碼,利用改編碼在2中得到的矩陣中得到對應顏色的索引;
- 利用3中得到的索引將R,G,B三個通道中的對應顏色值替換為目標值;
- 將得到的三個通道合并為一個圖像數據。
??具體實現如下:
def
replace_color
(
img
,
src_clr
,
dst_clr
)
:
''' 通過矩陣操作顏色替換程序
@param img: 圖像矩陣
@param src_clr: 需要替換的顏色(r,g,b)
@param dst_clr: 目標顏色 (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
三、結果對比
??先看下具體的實現結果,全部測試程序文末給出,(上面的圖片是原圖,下面是替換后的圖片)。
四、程序解釋
??通過如下方式編碼的原因是r,g,b三原色的數值本身是順序相關的,為了保證最后索引的一致與準確性,采用將不同數值錯位開。這里的magic number采用256是因為三原色的數值的范圍是[0,255],這樣相乘可以保證數據在二進制上的完全相互交錯而保證該編碼是絕對正確的,當然也可以采用其他形式的編碼或者數值選擇其他數值,我這樣選擇是為了保險起見而已。
img
=
r_img
*
256
*
256
+
g_img
*
256
+
b_img
src_color
=
src_clr
[
0
]
*
256
*
256
+
src_clr
[
1
]
*
256
+
src_clr
[
2
]
#編碼
五、完整的測試程序
??完整的程序:
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: 目標顏色 (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
)
#將數據轉換為圖像數據(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: 目標顏色 (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
(
'矩陣操作花費時間:'
,
matrix_time
/
count
)
print
(
'遍歷操作花費時間:'
,
trans_time
/
count
)
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

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