在圖像處理中,過濾背景即保留圖像的高頻信息可以有效地提升處理速度,提高計算機識別目標的精度,用到顯著性檢測算法可以較好地實現這也過程,接下來我將對這一過程進行闡述:
一、HC法
設矩陣A和矩陣B分別代表兩個不同的顏色那麼它們之間的歐式距離(代碼表示)爲:
matC=(matA-matB)
length=numpy.linalg.norm(matC)
即兩個矩陣相減後形成的矩陣的歐式範數(也即是幾何上的距離)
當然這個是HC法的定義,真正進行圖像處理的時候是不會直接用這個的,而是先計算圖片的像素直方圖,然後再對圖片的像素進行替換,形成顯著性檢測圖像。
二、獲得圖像直方圖以及各顏色歐式距離
使用OpenCV的函數以及matplotlib可以快速獲得直方圖以及繪製,並以此獲得各個顏色對於其他顏色的歐式距離。
import cv2
import numpy as np
import matplotlib.pyplot as plt
mat=cv2.imread('mat.jpg')#讀取圖片
def get_hist(mat):
hist=cv2.calcHist([mat],[0],None,[256],[0,256])#獲取直方圖的一維向量
a=np.zeros(256)#生成一個256長度的向量
for i in range(256): #對所有值進行遍歷
for j in range(256):
a[i]+=(i-j)**2*hist[j]#每次加上與這個像素的距離平凡並乘以像素數爲總和
a=np.sqrt(a)#開方處理
a=a*255/np.max(a)-0.001#縮小到255以內
gray_mat=a.astype(np.uint8)#轉換成8位
print(gray_mat)#驗證
return norm_mat#返回各個顏色的範數矩陣
三、對圖片進行遍歷以及像素快速替換
將圖片的所有值進行替換,形成一個顯著性檢測圖像。
def saliency_img(img_mat,norm_mat):
########################對圖像的每個像素進行遍歷處理,將每個像素進行替換
for i in range(img_mat.shape[0]):
for j in range(img_mat.shape[1]):
c=img_mat[i][j].astype(np.uint8)#轉換成八位
b[i][j]=norm_mat[c]
########################
b=b.astype(np.uint8)
print(b)
cv2.imshow('b',b)#顯示圖片
cv2.waitKey(0)
cv2.destroyAllWindows()
return b#返回顯著性檢測矩陣
當然,大家得知道一個原則,在圖片處理中,要儘量減少FOR循環的使用,儘量對圖片進行矢量化操作,對像素進行替換的時候使用numpy.where()函數很好。
註釋:
(1)numpy.where(condition,if_true,if_false)若condition爲1執行if_true
假爲if_false
(2)for i ,gray in enumerate(a): 這個遠比for in range快
print(i,gray)
等價於
for i in range(a.shape[0]):
print(i,a[i])
以下是上面代碼的另一種寫法:
def saliency_img(img_mat,norm_mat):
############################以下爲不同之處
b=img_mat
for i, norm in enumerate(norm_mat):
b=np.where(b==i,norm,b)
############################
saliency_img=b.astype(np.uint8)
cv2.imshow('b',saliency_img)#顯示圖片
cv2.waitKey(0)
cv2.destroyAllWindows()
return saliency_img#返回顯著性檢測矩陣
上面的代碼可以說提高了非常多的速度,同時壓縮了圖像處理的時間
四、直方圖均衡化和模糊處理(雙邊濾波)以及二值化
opencv的直方圖均衡化有兩種方法:
1、普通直方圖均衡化(對較量和較暗的圖像很好):
def equalize(img_mat):
cl1=cv2.equalizeHist(img_mat)
cv2.imshow('1',cl1)
cv2.waitKey(0)
cv2.destroyAllWindows()
return cl1
2`、有限對比適應性直方圖均衡化(可以較好的保留細節,但是較暗圖片處理不太好)
def gethist_patch(img_mat):
clahe=cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
cl1=clahe.apply(img_mat)
cv2.imshow('1',cl1)
cv2.waitKey(0)
cv2.destroyAllWindows()
然後是雙邊濾波圖像處理:
img=cv2.bilateralFilter(img,9,75,75)
圖像的二值化(不用opencv):
img=np.where(img>255*2/3,255,0)#大於255的三分之二的爲顯著區域
五、顯著性檢測函數(合併一二)
def visual_saliency_detection(mat):
hist = cv2.calcHist([mat], [0], None, [256], [0, 256]) # 獲取直方圖的一維向量
a = np.zeros(256) # 生成一個256長度的向量
for i in range(256): # 對所有值進行遍歷
for j in range(256):
a[i] += (i - j) ** 2 * hist[j] # 每次加上與這個像素的距離平凡並乘以像素數爲總和
a = np.sqrt(a) # 開方處理
a = a * 255 / np.max(a) - 0.001 # 縮小到255以內
a = a.astype(np.uint8) # 轉換成8位
print(a)
b=mat
for i, gray in enumerate(a):
b=np.where(b==i,gray,b)
b=b.astype(np.uint8)
cv2.imshow('b',b)
cv2.waitKey(0)
cv2.destroyAllWindows()
return b
六、實驗現象
原圖像
顯著性檢測圖像
二值化圖像