程序簡介
程序調用Python的opencv模塊,根據拉普拉斯變換計算像素方差來作為圖片的模糊程度和遮擋程度的指標值,然后根據參考值構建正態分布,根據3西格瑪准則,判斷圖片是否異常,最終實現了模糊檢測和遮擋檢測功能。但是本程序使用的數據集為從VOC2007隨機選擇的圖片,對於固定場景,最好選擇對應場景的圖片集,以及調整正確的參數。
拉普拉斯變換是工程數學中常用的一種積分變換,也可以用作邊緣檢測。
3西格瑪准則又稱為拉依達准則,它是先假設一組檢測數據只含有隨機誤差,對其進行計算處理得到標准偏差,按一定概率確定一個區間,認為凡超過這個區間的誤差,就不屬於隨機誤差而是粗大誤差,含有該誤差的數據應予以剔除。
程序/數據集下載
代碼分析
導入模塊、路徑
# -*- coding: utf-8 -*-
from tqdm import tqdm
import numpy as np
import cv2
構建calLaplacianVar函數,用來對圖片進行進行拉普拉斯變換和計算方差
def calLaplacianVar(img,size=None):
'''
計算拉普拉斯方差,圖片越模糊,其邊緣就越少
所以該方法可用於模糊檢測、遮擋檢測,衡量圖片信息量
img:opencv圖像矩陣
size:重定尺寸(寬,高)
'''
#灰度化圖片
if len(img.shape) == 3:
grayImg = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
else:
grayImg = img.copy()
#重定尺寸,轉矩陣為張量
if size is not None:
grayImg = cv2.resize(grayImg,size)
#經過拉普拉斯變換的圖片
transeImg = cv2.Laplacian(grayImg, cv2.CV_64F)
#拉普拉斯方差
imgVar = transeImg.var()
return imgVar
構建ViewEvaluate類,其中evalDist函數用來讀取特定文件夾下所有圖片,計算出所有指標值,並形成分布,judgeOutlie作為接口,判斷一張圖片是否異常,此處使用1.5倍標准差作為異常判斷標准
class ViewEvaluate():
def __init__(self,imgDir,size,sigmaTimes=1.5):
'''
利用拉普拉斯方差和均方差假設檢驗的方法進行視野評估
imgDir:用於計算分布的圖片目錄
size:重定圖片(寬,高)
sigmaTimes:標准差倍數內認為是正常值
'''
self.imgDir = imgDir
self.size = tuple(size)
self.sigmaTimes = sigmaTimes
self.evalDist()
def evalDist(self):
'''
計算圖片目錄下所有圖片的指標,形成分布
'''
imgNames = tqdm(os.listdir(imgDir))#圖片名列表
values = []#指標列表
#計算所有圖片的指標
for index,name in enumerate(imgNames):
imgNames.set_description("計算圖片分布")
path = imgDir + '/' + name
img = cv2.imdecode(np.fromfile(path,dtype = np.uint8),-1)
value = calLaplacianVar(img,size=self.size)
values.append(value)
values = np.array(values)
#假設正常圖片指標值近似正太分布,計算正常值范圍
sigma = values.std()#標准差
u = values.mean()#均值
self.photoArea = [u-self.sigmaTimes*sigma,u+self.sigmaTimes*sigma]
print("當前分布均值%d,標准差%d 正常區間[%d , %d]"%(u,sigma,self.photoArea[0],self.photoArea[1]))
def judgeOutlier(self,img):
'''
判斷該圖片是否異常(0正常 1異常)以及指標值
img:opencv圖像矩陣
'''
value = calLaplacianVar(img,size=self.size)
judgement = 0#異常判斷
if value < self.photoArea[0]:
judgement = 1
mark = "異常" if judgement else "正常"
print("當前圖片指標值為:%d,%s"%(value,mark))
return judgement,value
對程序進行測試,對原圖進行遮擋和模糊化,然后用程序進行判斷
import os
#路徑目錄
baseDir = ""#當前目錄
staticDir = os.path.join(baseDir,'Static')#靜態文件目錄
resultDir = os.path.join(baseDir,'Result')#結果文件目錄
imgDir = staticDir+'/img'
size = (250,250)
sigmaTimes = 1
viewEvaluate = ViewEvaluate(imgDir,size,sigmaTimes)
#本地測試
path = imgDir + '/003713.jpg'
color = (0,0,255)
img = cv2.imdecode(np.fromfile(path,dtype = np.uint8),-1)
img1 = img.copy()
judgement,value = viewEvaluate.judgeOutlier(img1)
if not judgement:
mark = "good"
else:
mark = "bad"
text = "status:%s value:%d"%(mark,value)
cv2.putText(img1, text, (30, 30), cv2.FONT_HERSHEY_PLAIN, 2.4, color, 2)
#遮擋測試
img2 = img.copy()
cv2.rectangle(img2,(0,175),(500,375),(0,0,0),-1)
judgement,value = viewEvaluate.judgeOutlier(img2)
if not judgement:
mark = "good"
else:
mark = "bad"
text = "status:%s value:%d"%(mark,value)
cv2.putText(img2, text, (30, 30), cv2.FONT_HERSHEY_PLAIN, 2.4, color, 2)
#模糊測試
img3 = cv2.medianBlur(img, 11)
judgement,value = viewEvaluate.judgeOutlier(img3)
if not judgement:
mark = "good"
else:
mark = "bad"
text = "status:%s value:%d"%(mark,value)
cv2.putText(img3, text, (30, 30), cv2.FONT_HERSHEY_PLAIN, 2.4, color, 2)
#合並3張測試圖
combine = np.hstack([img1,img2,img3])
combine = cv2.resize(combine,(900,300))
cv2.imencode('.jpg',combine)[1].tofile(resultDir+'/test.jpg')
cv2.imshow('',combine)
計算圖片分布: 100%|████████████████████████████████| 102/102 [00:01<00:00, 87.70it/s]
當前分布均值2234,標准差1423 正常區間[810 , 3658]
當前圖片指標值為:1564,正常
當前圖片指標值為:263,異常
當前圖片指標值為:83,異常
從左至右分別為原圖、遮擋圖和模糊圖,對圖片的判斷寫在了圖片上方