opencv 传统图像识别检测

一、图像相识度检测

读取图像哈希列表数据 pash计算结构,hash距离低于该值的都判定为相似图像

import cv2

import shutil

import numpy as np

import os

def main(hashPath, savePath, pashThre):

# 读取图像哈希列表数据

hashList = np.load(hashPath, allow_pickle=True).item()

# 创建图像结果保存文件夹

os.makedirs(savePath, exist_ok=True)

# pash计算结构

phashStruct = cv2.img_hash.PHash_create()

while len(hashList):

# 取keys

now_keys = list(hashList.keys())[0]

# 还剩多少图像

print("待处理图像{}张".format(len(hashList.keys())))

nowKeyValue = hashList.pop(now_keys)

# 相同图像存储

similarFilename = []

# 循环计算值

for keys in hashList:

pashValue = phashStruct.compare(nowKeyValue, hashList[keys])

if pashValue <= pashThre:

similarFilename.append(keys)

try:

# 移动图像

if len(similarFilename) > 0:

# 获得关键key名字

nowKeyFilename = os.path.basename(now_keys)

# 创建的保存文件路径

saveFilePath = os.path.join(savePath, nowKeyFilename[:-4])

os.makedirs(saveFilePath, exist_ok=True)

# 移动关键keys图像

# shutil.move(now_keys,os.path.join(saveFilePath,nowKeyFilename))

# 从字典中移除值,并移动或者复制图像

for i in similarFilename:

hashList.pop(i)

# 获得key名字

keyFilename = os.path.basename(i)

# 复制图像,移动图像就把copy改为move

shutil.copy(i, os.path.join(saveFilePath, keyFilename))

except:

continue

if __name__ == '__main__':

# hash文件路径

hashPath = "hash_result.npy"

savePath = "similarImg"

# hash距离低于该值的都判定为相似图像

pashThre = 5

main(hashPath, savePath, pashThre)

读取图像计算hash值

import threading

import queue

import cv2

import os

import numpy as np

# 计算图像hash值

def consume(threadName, q, result):

while True:

fileName, img = q.get()

# 图像不存在已有结果中就重新计算

# 判断图像是否有hash记录可以读取图像函数中,执行更高效。

# 放在这里主要是担心图像出问题

if str(fileName) not in result.keys():

phashValue = cv2.img_hash.PHash_create().compute(img)

result[str(fileName)] = phashValue

print('{} processing img: {}'.format(threadName, fileName))

q.task_done()

# 读取图像

def produce(threadName, q, imgPath):

for i in os.listdir(imgPath):

if i.split('.')[-1].lower() in ['jpg', 'png']:

fileName = os.path.join(imgPath, i)

img = cv2.imread(fileName)

if img is None:

continue

q.put([fileName, img])

print('{} reading img: {}'.format(threadName, fileName))

q.join()

def main(imgPath, savePath):

# 结果

result = {}

# 读取已有结果加快速度

if os.path.exists(savePath):

result = np.load(savePath, allow_pickle=True).item()

q = queue.Queue()

# 1个读图线程

p = threading.Thread(target=produce, args=("producer", q, imgPath))

# 4个计算线程

c1 = threading.Thread(target=consume, args=("consumer1", q, result))

c2 = threading.Thread(target=consume, args=("consumer2", q, result))

c3 = threading.Thread(target=consume, args=("consumer3", q, result))

c4 = threading.Thread(target=consume, args=("consumer4", q, result))

c1.setDaemon(True)

c2.setDaemon(True)

c3.setDaemon(True)

c4.setDaemon(True)

# 启线程

p.start()

c1.start()

c2.start()

c3.start()

c4.start()

p.join()

# 保存结果

np.save(savePath, result)

if __name__ == '__main__':

# 检测文件夹

imgPath = 'C:\py\code\yolov5-flask-master\imgs'

# 结果保存路径

savePath = "hash_result.npy"

main(imgPath, savePath)

二、黑屏检测

计算偏离128的平均偏差获得亮度系数,当亮度系数低于某一阈值的时候就认为他出现黑屏

import cv2

img = cv2.imread(r'C:\py\code\yolov5-flask-master\imgs\brightness\img1.png')

# 把图片转换为单通道的灰度图

gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 获取灰度图矩阵的行数和列数

r, c = gray_img.shape[:2]

piexs_sum = r * c # 整个弧度图的像素个数为r*c

# 获取偏暗的像素(表示0~19的灰度值为暗) 此处阈值可以修改

dark_points = (gray_img < 20)

target_array = gray_img[dark_points]

dark_sum = target_array.size

# 判断灰度值为暗的百分比

dark_prop = dark_sum / (piexs_sum)

if dark_prop >= 0.85:

print("黑屏了")

else:

print("正常了")

三、遮挡检测

将帧转换为灰度图像,然后使用阈值进行二值化。然后,查找二值化图像中的轮廓。如果找到的轮廓数量超过某个阈值,就认为有遮挡。

import cv2

import numpy as np

# 读取视频

cap = cv2.VideoCapture(0)

while(cap.isOpened()):

# 读取帧

ret, frame = cap.read()

if not ret:

break

# 转换为灰度图像

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# 使用阈值进行二值化,以检测遮挡

ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# 查找轮廓

contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 如果找到的轮廓数量超过某个阈值,则认为有遮挡

if len(contours) > 300:

print("contours:",len(contours))

print("遮挡检测到")

# 显示帧

cv2.imshow('frame', frame)

if cv2.waitKey(1) & 0xFF == ord('q'):

break

# 释放资源并关闭窗口

cap.release()

cv2.destroyAllWindows()

四、图像过亮和过暗检测

计算偏离128的平均偏差获得亮度系数

import cv2

import matplotlib.pyplot as plt

import numpy as np

import time

image_path = r'C:\py\code\yolov5-flask-master\imgs\brightness\img1.png'

def brightness(frame):

# 把图片转换为单通道的灰度图

gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# 获取形状以及长宽

img_shape = gray_img.shape

height, width = img_shape[0], img_shape[1]

size = gray_img.size

# 灰度图的直方图

hist = cv2.calcHist([gray_img], [0], None, [256], [0, 256])

# 计算灰度图像素点偏离均值(128)程序

a = 0

ma = 0

# np.full 构造一个数组,用指定值填充其元素

reduce_matrix = np.full((height, width), 128)

shift_value = gray_img - reduce_matrix

shift_sum = np.sum(shift_value)

da = shift_sum / size

# 计算偏离128的平均偏差

for i in range(256):

ma += (abs(i - 128 - da) * hist[i])

m = abs(ma / size)

# 亮度系数

k = abs(da) / m

# print(k[0])

if k[0] > 1:

# 过亮

if da > 0:

print("过亮")

else:

print("过暗")

# else:

# print("亮度正常")

cap = cv2.VideoCapture(0)

start = time.time()

while True:

# 读取当前帧和下一帧

ret1, frame1 = cap.read()

ret2, frame2 = cap.read()

# 显示画面

cv2.imshow('frame', frame1)

brightness(frame1) #过亮过暗检测

# 监测键盘输入是否为q,为q则退出程序

if cv2.waitKey(1) & 0xFF == ord('q'):

break

# 释放视频资源

cap.release()

# 关闭所有窗口

cv2.destroyAllWindows()

五、清晰度检测

利用拉普拉斯算子计算图片的二阶导数,反映图片的边缘信息,同样事物的图片,清晰度高的,相对应的经过拉普拉斯算子滤波后的图片的方差也就越大。

import cv2

image_path = r'C:\py\code\yolov5-flask-master\imgs\clarity\img3.png'

threshold = 150

#利用拉普拉斯

def getImageVar(imgPath):

image = cv2.imread(imgPath)

img2gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

imageVar = cv2.Laplacian(img2gray, cv2.CV_64F).var()

return imageVar

imageVar = getImageVar(image_path)

# 判断亮度是否低于阈值

if imageVar < threshold:

print(imageVar,"图片不清晰")

else:

print(imageVar,"图片正常")

print("拉普拉斯:",imageVar)

六、偏色检测

读取图像,将其转换为LAB色彩空间,计算a和b分量的均值和方差,最后输出图像的色偏值

import cv2

img = cv2.imread(r'C:\py\code\yolov5-flask-master\imgs\brightness\img1.png')

img = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)

l_channel, a_channel, b_channel = cv2.split(img)

h,w,_ = img.shape

print("ssssssss",a_channel.sum()/(h*w) )

da = a_channel.sum()/(h*w)-128

db = b_channel.sum()/(h*w)-128

histA = [0]*256

histB = [0]*256

for i in range(h):

for j in range(w):

ta = a_channel[i][j]

tb = b_channel[i][j]

histA[ta] += 1

histB[tb] += 1

msqA = 0

msqB = 0

for y in range(256):

msqA += float(abs(y-128-da))*histA[y]/(w*h)

msqB += float(abs(y - 128 - db)) * histB[y] / (w * h)

import math

result = math.sqrt(da*da+db*db)/math.sqrt(msqA*msqA+msqB*msqB)

print("d/m = %s"%result)

七、对比度检测

使用了帧差法来检测画面中是否有物体在运动。具体来说,它每隔一段时间采集一幅图片,通过比较前后两幅图片像素变化来判断画面中是否有物体在运动。如果两幅图的差异大于给定的值,认为画面中有物体在动;反之则认为画面中没有物体在运动

import cv2

import time

import numpy as np

cap = cv2.VideoCapture(0)

_, frame1 = cap.read()

img1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)

start = time.time()

def moving_detect(frame1, frame2):

img1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)

img2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)

grey_diff = cv2.absdiff(img1, img2)

change = np.average(grey_diff)

if change > 10:

cv2.putText(frame2, 'moving', (100, 30), 2, 1, (0,255,0),2,cv2.LINE_AA)

else:

cv2.putText(frame2, 'quiet', (100, 30), 2, 1, (255, 0, 0), 2, cv2.LINE_AA)

cv2.imshow("output", frame2)

while True:

end = time.time()

if (end - start > 2):

start = time.time()

_, frame1 = cap.read()

_, frame2 = cap.read()

moving_detect(frame1, frame2)

if cv2.waitKey(5) & 0xFF == ord('q'):

break

cap.release()

cv2.destroyAllWindows()

八、冻结检测

import cv2

import numpy as np

cap = cv2.VideoCapture(0)

ret, frame = cap.read()

gray_prev = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

count = 0

while True:

ret, frame = cap.read()

cv2.imshow('frame', frame)

if not ret:

break

count += 1

if count % 40 != 0:

continue

gray_curr = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

hist_curr = cv2.calcHist([gray_curr], [0], None, [256], [0, 256])

hist_prev = cv2.calcHist([gray_prev], [0], None, [256], [0, 256])

similarity = cv2.compareHist(hist_curr, hist_prev, cv2.HISTCMP_CORREL)

print(f"检测视频有无冻结相识度: {count-40} and {count}: {similarity}")

gray_prev = gray_curr

# 监测键盘输入是否为q,为q则退出程序

if cv2.waitKey(1) & 0xFF == ord('q'):

break

cap.release()

# 关闭所有窗口

cv2.destroyAllWindows()

九、噪点检测

将图像转换为灰度图像,计算图像的均值和标准差,再计算图像的方差

import cv2

image_path = r'C:\py\code\yolov5-flask-master\imgs\noise\img3.png'

# 阈值

threshold =4

# 读取图像

img = cv2.imread(image_path)

# 将图像转换为灰度图像

gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 计算图像的均值和标准差

mean, stddev = cv2.meanStdDev(gray_img)

# 计算图像的方差

variance = (stddev ** 2)/1000

if(variance>threshold):

print("图片噪声过高")

else:

print("图片噪声正常")

print("Mean: ", mean[0][0], " Standard deviation: ", stddev[0][0])

print("The variance of the image is:", variance[0][0])

十、 条纹检测

使用傅里叶变换检测图像中的条纹。它首先将图像转换为灰度图像,然后对其进行傅里叶变换。通过将频谱图中心化,可以将低频分量移动到图像的中心,而高频分量则移动到图像的边缘。通过将高频分量设置为零,可以滤除图像中的条纹。最后,通过阈值处理和轮廓检测,可以确定图像是否存在条纹

import cv2

import numpy as np

def stripeDetection(frame):

# img = cv2.imread(imgPath)

img_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

H = cv2.split(img_hsv)[0]

# 傅里叶变换

f = np.fft.fft2(H)

r, c = f.shape

fshift = np.fft.fftshift(f)

# 计算频谱图的异常亮点数

# f_img = 20 * np.log(np.abs(f))

magnitude_spectrum = 20 * np.log(np.abs(fshift))

matrix_mean = np.mean(magnitude_spectrum)

# 计算阈值

matrix_std = np.std(magnitude_spectrum)

# 最大值

matrix_max = magnitude_spectrum.max()

# 计算阈值(均值加3倍标准差 和 最大值/2 中大的值为阈值)

T = max(matrix_mean + 3 * matrix_std, matrix_max / 2)

# 将小于T的变为0

# magnitude_spectrum[magnitude_spectrum < T] = 0

# 统计大于T的点数

magnitude_points = (magnitude_spectrum >= T)

target_array = magnitude_spectrum[magnitude_points]

magnitude_sum = target_array.size

streak_rate = magnitude_sum / (c * r)

print("条纹率", streak_rate)

if streak_rate > 0.004:

return "图片条纹"

else:

return "图片正常"

image_path = r'C:\py\code\yolov5-flask-master\imgs\img4.png'

cap = cv2.VideoCapture(0)

# 读取摄像头画面

ret, frame = cap.read()

while True:

ret, frame = cap.read()

# 判断是否读取到帧

if not ret:

break

imageVar = stripeDetection(frame)

print(imageVar)

# 显示画面

cv2.imshow('frame', frame)

# 按下q键退出循环

if cv2.waitKey(1) & 0xFF == ord('q'):

break

十一、视频抖动检测

我们将计算每帧的光流,并将结果作为视频抖动的一个指标。通过sim计算图像相识度,设定好阈值后也可以完成检测。

import cv2 as cv

import cv2

import numpy as np

import os

#

#

#

path = 'C:/py/code/yolov5-flask-master/imgs/videoJitter/video1.mp4'

# threshold = 20000;

# # 读取视频

# cap = cv2.VideoCapture(path)

#

# # 初始化光流对象

# # optical_flow = cv2.createOptFlow_DualTVL1()

# # TVL1 = cv2.optflow.DualTVL1OpticalFlow()

# TVL1 = cv2.optflow.DualTVL1OpticalFlow_create()

#

#

# # 初始化变量来存储光流的总和

# total_flow = 0

#

# # 计数器

# frame_count = 0

#

# while (cap.isOpened()):

# ret, frame = cap.read()

# if ret == True:

# # 将BGR图像转换为灰度图像

# gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

#

# # 如果不是第一帧,则计算光流

# if frame_count > 0:

# flow = TVL1.calc(prev_gray, gray, None)

#

# # 计算光流的绝对值的总和

# total_flow += np.sum(np.abs(flow))

#

# # 更新前一帧

# prev_gray = gray

#

# # 显示当前帧

# cv2.imshow('frame', frame)

#

# # 增加计数器

# frame_count += 1

#

# # 按q键退出

# if cv2.waitKey(1) & 0xFF == ord('q'):

# break

# else:

# break

#

# # 计算平均光流

# avg_flow = total_flow / frame_count

#

# # 判断是否存在抖动

# if avg_flow > threshold:

# print("Video is shaky")

# else:

# print("Video is stable")

#

# # 打印结果

# print("Average Optical Flow: ", avg_flow)

#

# # 释放资源并关闭窗口

# cap.release()

# cv2.destroyAllWindows()

#

#

# # videos = os.listdir(path)

# # TVL1 = cv.optflow.DualTVL1OpticalFlow_create()

# # for video in videos:

# # video_path = path + '/' + video

# # cap = cv.VideoCapture(video_path)

# # ret, frame1 = cap.read()

# # prvs = cv.cvtColor(frame1, cv.COLOR_BGR2GRAY)

# # hsv = np.zeros_like(frame1)

# # hsv[..., 1] = 255

# # count = 0

# # while (True):

# # ret, frame2 = cap.read()

# # if not ret:

# # break

# # next = cv.cvtColor(frame2, cv.COLOR_BGR2GRAY)

# #

# # # 返回一个两通道的光流向量,实际上是每个点的像素位移值

# # flow = TVL1.calc(prvs, next, None)

# #

# # # 打印结果

# # print("Average Optical Flow: ", flow)

# #

# # # 笛卡尔坐标转换为极坐标,获得极轴和极角

# # mag, ang = cv.cartToPolar(flow[..., 0], flow[..., 1])

# #

# # hsv[..., 0] = ang * 180 / np.pi / 2 # 角度

# # hsv[..., 2] = cv.normalize(mag, None, 0, 255, cv.NORM_MINMAX)

# # bgr = cv.cvtColor(hsv, cv.COLOR_HSV2BGR)

# # path_ = path + '/' + os.path.basename(video).split('.')[0]

# # if not os.path.exists(path_):

# # os.makedirs(path_)

# # # cv.imwrite(path_ + "/frame{0:06d}.jpg".format(count), bgr)

# # count += 1

# # prvs = next

# # cap.release()

# # cv.destroyAllWindows()

# 读取视频文件

video = cv2.VideoCapture(0)

# 定义一个函数,用于计算两帧之间的相似度

def similarity(frame1, frame2):

# 将两帧转换为灰度图

gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)

gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)

# 计算两帧的直方图

hist1 = cv2.calcHist([gray1], [0], None, [256], [0, 256])

hist2 = cv2.calcHist([gray2], [0], None, [256], [0, 256])

# 使用卡方距离作为相似度的度量

dist = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CHISQR)

return dist

# 定义一个阈值,用于判断是否发生抖动

threshold = 23000

# 初始化一个列表,用于存储抖动的帧数

shaky_frames = []

# 初始化一个变量,用于记录当前的帧数

frame_count = 0

# 循环读取视频的每一帧

while True:

# 读取当前帧和下一帧

ret1, frame1 = video.read()

ret2, frame2 = video.read()

# 显示画面

cv2.imshow('frame', frame1)

# 如果读取成功,继续处理

if ret1 and ret2:

# 计算当前帧和下一帧的相似度

sim = similarity(frame1, frame2)

print("计算当前帧和下一帧的相似度",sim)

# 如果相似度大于阈值,说明发生了抖动

if sim > threshold:

# 将当前帧的帧数添加到列表中

shaky_frames.append(frame_count)

print("视频开始抖动", sim)

# 更新帧数

frame_count += 1

# 如果读取失败,退出循环

else:

break

# 监测键盘输入是否为q,为q则退出程序

if cv2.waitKey(1) & 0xFF == ord('q'):

break

# 释放视频资源

video.release()

# 关闭所有窗口

cv2.destroyAllWindows()

# 打印抖动的帧数

print("The following frames are shaky:")

print(shaky_frames)

十二、视频卡顿检测

每隔40帧取一帧和前面做对比

def freezeDetection(cap):

ret, frame = cap.read()

gray_prev = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

count = 0

while True:

ret, frame = cap.read()

# cv2.imshow('frame', frame)

if not ret:

break

count += 1

if count % 40 != 0:

continue

gray_curr = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

hist_curr = cv2.calcHist([gray_curr], [0], None, [256], [0, 256])

hist_prev = cv2.calcHist([gray_prev], [0], None, [256], [0, 256])

similarity = cv2.compareHist(hist_curr, hist_prev, cv2.HISTCMP_CORREL)

gray_prev = gray_curr

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: