1-- 前言
评估方法均为网上查询的传统图像处理方法,检测效果不是很好,仅供参考。
2-- 条纹干扰诊断
# 条纹干扰诊断
'''
诊断方法:参考https://github.com/ChengHaoHappy/VideoQualityDetection/blob/master/StripeDetect.cpp
https://www.cnblogs.com/wqvbjhc/p/3768995.html
'''
import cv2
import numpy as np
def streak_diagnosis(image):
img_HSV = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 转HSV
img_H = img_HSV[:, :, 0] # 取色度
best_row = cv2.getOptimalDFTSize(img_H.shape[0]) # 返回给定向量尺寸经过DFT变换后的最优尺寸大小
best_line = cv2.getOptimalDFTSize(img_H.shape[1])
# 下面这段代码的作用是扩充img_H图像,新增像素点的像素值为0
temp = np.zeros((best_row, best_line))
temp[:img_H.shape[0], :img_H.shape[1]] = img_H
img_H = temp
img_dft = cv2.dft(np.float32(img_H), flags = cv2.DFT_COMPLEX_OUTPUT) # 傅里叶变换
img_dft = np.fft.fftshift(img_dft)
mRe = img_dft[:, :, 0] # 实部
mIm = img_dft[:, :, 1] # 虚部
# 计算二维矢量的幅值
img_value = cv2.magnitude(mRe, mIm)
# 转为自然对数
img_value = 20 * np.log(img_value)
# 计算均值和标准差
means, std = cv2.meanStdDev(img_value)
# 计算最大值和最小值
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(img_value)
# 计算阈值
T = float(max(means+3*std, maxVal/2))
r, l = img_value.shape
count = 0 # 统计异常点的个数
for i in range(r):
for j in range(l):
if img_value[i, j] > T:
count = count + 1
stripe_rate = count / (r*l) # 计算条纹率
if (stripe_rate > 0.008):
print("条纹干扰异常")
else:
print("条纹干扰正常")
if __name__ == '__main__':
img_path = '/civi/Video_and_Image_Diagnostics/streak_test1.jpg'
img = cv2.imread(img_path, cv2.IMREAD_COLOR)
streak_diagnosis(img)
3-- 视频抖动检测
# 视频抖动诊断
# 诊断方法,参考网页:https://www.it610.com/article/1303919958840872960.htm
import numpy as np
import cv2
# 计算行投影值
def cal_row_projection(image_frame):
rows = image_frame.shape[0] # 输入图像帧的行数
lines = image_frame.shape[1] # 输入图像帧的列数
single_row_sum = np.zeros([rows, 1])
all_rows_sum = 0
for i in range(rows): # 遍历每一行 # 函数也可以用numpy.sum实现
for j in range(lines): # 遍历每一列
single_row_sum[i] = single_row_sum[i] + image_frame[i, j] # 对每一行求和
all_rows_sum = all_rows_sum + single_row_sum[i] # 所有行的灰度值求和
avg_rows_sum = all_rows_sum / rows # 所有行灰度值总和的行平均值
return (single_row_sum - avg_rows_sum) # rows*1
# 计算列投影值
def cal_line_projection(image_frame):
rows = image_frame.shape[0] # 输入图像帧的行数
lines = image_frame.shape[1] # 输入图像帧的列数
single_line_sum = np.zeros([lines, 1])
all_lines_sum = 0
for i in range(lines): # 遍历每一列 # 函数也可以用numpy.sum实现
for j in range(rows): # 遍历每一行
single_line_sum[i] = single_line_sum[i] + image_frame[j, i] # 对每一列求和
all_lines_sum = all_lines_sum + single_line_sum[i] # 所有列的灰度值求和
avg_lines_sum = all_lines_sum / lines # 所有行灰度值总和的行平均值
return (single_line_sum - avg_lines_sum) # lines*1
# 计算互相关最小值
def cal_min(img_frame_projection, ref_frame_projection, m): # 第一个参数为当前输入帧, 第二个参数为参考帧(一般取前一个帧)
min_value = 999999999999 # 最小的互相关值
idx = 0
for w in range(2*m+1):
w = w + 1 # 从1开始遍历
sum_diff = 0
for j in range(img_frame_projection.shape[0] - 2*m):
sum_diff = (img_frame_projection[j + w - 1] - ref_frame_projection[m + j])**2
if (sum_diff < min_value):
min_value = sum_diff # 更新最小互相关值
idx = w # 记录当前的w值
return (m + 1 - min_value) # 返回位移矢量
# 抖动检测
def shake_detection(img_frame, ref_frame):
m = 20
threshold = 10 # 设置偏移阈值大小
img_row_projection = cal_row_projection(img_frame) # 计算输入帧图像的行投影值
img_line_projection = cal_line_projection(img_frame) # 计算输入帧图像的列投影值
ref_row_projection = cal_row_projection(ref_frame) # 计算输入帧图像的行投影值
ref_line_projection = cal_line_projection(ref_frame) # 计算输入帧图像的列投影值
row_shift_val = cal_min(img_row_projection, ref_row_projection, m)
line_shift_val = cal_min(img_line_projection, ref_line_projection, m)
if (row_shift_val > threshold) or (line_shift_val > threshold):
print("抖动异常")
else:
print("抖动正常")
if __name__ == '__main__':
cap = cv2.VideoCapture('/civi/Video_and_Image_Diagnostics/car1.mp4')
frame_sum = 0
frame = []
last_frame = []
flag = 0
while True:
if frame_sum > 1:
last_frame = frame
flag = 1
ret, frame = cap.read() # 读取视频
if ret is False: # 当所有帧读取完毕后退出循环
print('视频读取失败 or 视频读取完毕')
break
else:
frame_sum = frame_sum + 1
if flag == 1:
cur_img_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 彩色图像转灰度图
last_img_gray = cv2.cvtColor(last_frame, cv2.COLOR_BGR2GRAY) # 彩色图像转灰度图
shake_detection(cur_img_gray, last_img_gray)
4-- 场景变更诊断
# 场景变更诊断
'''
对彩色图像进行高斯建模,
提取高斯建模后的前景图像,
计算前景图像的变化量,若大于设定值后,则报警。
'''
import cv2
import numpy as np
if __name__ == '__main__':
# 构造VideoCapture对象
cap = cv2.VideoCapture('/civi/Video_and_Image_Diagnostics/car1.mp4')
pBackgroundMOG = cv2.bgsegm.createBackgroundSubtractorMOG() # 创建一个背景分割器
frame_sum = 0
FGMask = []
last_FGMask = []
change_thresh = 100
while True:
ret, frame = cap.read() # 读取视频
if ret is False: # 当所有帧读取完毕后退出循环
print('视频读取失败 or 视频读取完毕')
break
else:
frame = cv2.resize(frame, (0, 0), fx=0.3, fy=0.3)
frame_sum = frame_sum + 1
if frame_sum > 1:
last_FGMask = FGMask # 前一帧的前景图
FGMask = pBackgroundMOG.apply(frame) # 当前帧的前景图
#cv2.imshow('frame', frame) # 显示当前原始帧
#cv2.imshow('FGMask', FGMask) # 显示当前帧的前景图像
#if frame_sum > 1:
#cv2.imshow('last_FGMask', last_FGMask) # 显示前一帧的前景图像
#if cv2.waitKey(10) & 0xff == 27: # 按ESC键退出
#break
if frame_sum > 1:
change = cv2.absdiff(FGMask, last_FGMask) # 计算当前帧和前一帧的前景差异
if np.mean(change) > change_thresh: # 与设定的阈值比较
print("场景异常")
break
else:
print("场景正常")
cap.release()
未完待续!