在图像处理中,过滤背景即保留图像的高频信息可以有效地提升处理速度,提高计算机识别目标的精度,用到显著性检测算法可以较好地实现这也过程,接下来我将对这一过程进行阐述:
一、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
六、实验现象
原图像
显著性检测图像
二值化图像
看起来也许效果比较差,但是如果用在背景比较干净的图里效果是很好的