opencv 传统图像识别检测
2023-12-20 19:47:56
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
文章来源:https://blog.csdn.net/m0_57968888/article/details/135109193
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!