smd2 灰度差分乘积法,速度感觉略慢,因为要遍历每个像素,一个像素与右边像素的差sub1 及与下面像素的差sub2,然后求积,score = abs(sub1)*abs(sub2), 将所有像素的score 累加 得出scores。 scores值越大说明边缘越多,图像越清晰。
下面将smd2封装成一个类。
其中def saveImage(self, imageList): # 保存清晰图片 可以选择注释掉,只是保存图片到本地而已。
该类需要传入一组图片的list,设置需要求出的最清晰的topK 张图片, 求的方法就是在一个scores 数组中求topk问题,直接用最小堆就行,python代码简单粗暴到不行,就一行语句!!
import os
import cv2
import numpy as np
import heapq
#global temi
#temi = 0
class SMD2:
def __init__(self, imageList, topk=3):
print("SMD2模糊检测 ")
self.imageList = imageList # 图片list
self.topk = topk # 检测最不模糊的k张
def TestSMD2(self):
scores = []
for i in range(len(self.imageList)):
score = self.SMD2Work(self.imageList[i])
print("分数判定,处理第 ", i, " 张图片, score = ", score)
scores.append(score)
maxScoreIndex = self.getListMaxNumIndex(scores, self.topk)
topkClearImageList = [] # 存放最清晰的图片list
for j in range(len(maxScoreIndex)):
print("分数最大的图片 ", j, " ,score = ", scores[maxScoreIndex[j]])
topkClearImageList.append(self.imageList[maxScoreIndex[j]])
self.saveImage(topkClearImageList) # 保存筛选出来的图片
return topkClearImageList
def SMD2Work(self, image): # 灰度差分乘积,速度慢
height, width = image.shape[:2]
image = cv2.resize(image, (int(width/2.2), int(height/2.2)))
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
f = np.matrix(gray) / 255.0 # 返回矩阵
x, y = f.shape
score = 0
for i in range(x - 1):
for j in range(y - 1):
score += np.abs(f[i+1,j]-f[i,j])*np.abs(f[i,j]-f[i,j+1])
return score
def getListMaxNumIndex(self, num_list, topk): # 返回最大k个值的下标
max_num_index = map(num_list.index, heapq.nlargest(topk, num_list))
#max_num_index = map(num_list.index, heapq.nsmallest(topk,num_list))
max_num_index = list(max_num_index) # 需转成list
return max_num_index
def saveImage(self, imageList): # 保存清晰图片
#global temi
saveDir = "./SMD2Detection/"
if not os.path.exists(saveDir):
os.makedirs(saveDir)
for i in range(len(imageList)):
#imgPath = saveDir + str(temi) + ".jpg"
imgPath = saveDir + str(i) + ".jpg"
cv2.imwrite(imgPath, imageList[i])
#print("保存第 ", temi, " 张最清晰的图片")
print("保存第 ", i, " 张最清晰的图片")
#temi += 1
return
另外的代码就是从一个视频中隔一段时间抽若干张图片出来,比如隔10秒抽20张图片出来,然后再从这20张图片选最清晰的to pK张图片,就是调用上面这个类。
代码随便写的。
if __name__ == "__main__":
videoP = "/Users/cmq/Desktop/Internship/ZCW_headDetection/video/桂_1/test2.avi"
cap = cv2.VideoCapture(videoP)
ret = True
# 每隔perframe张抽相邻getframe张,找出topk张最清晰的,视频走完stopframe帧后终止
count = 0
stopframe = 1000
topk = 3
perframe = 100
getframe = 10
imgList = []
append_flag = True
while(cap.isOpened and ret and count != stopframe):
ret, frame = cap.read()
if count % perframe == 0:
append_flag = True
if append_flag:
imgList.append(frame)
if count % perframe == getframe:
append_flag = False
smd2 = SMD2(imgList) # 检测
smd2.TestSMD2()
imgList = []
count += 1
最主要是上面的smd2类~
smd2 = SMD2(imgList) # 创建对象,默认topk=3
smd2.TestSMD2() # 开始计算