其他分享
首页 > 其他分享> > 第五节课·基于图像相似度比较分镜头

第五节课·基于图像相似度比较分镜头

作者:互联网

目录

基本思路:

5.1 将视频打散为图片

5.2比较图像相似度

5.2.1 基于相等比较图像相似度

5.2.2 基于numpy计算图片是否相等

5.2.3 基于哈希(以均值哈希算法为例)

5.3 视频截取:ffmpeg

5.4 综合运用


基本思路:

1.将视频打散为图片

2.选择合适的方法(相等、numpy、哈希)比较图像相似度

3.根据相似度,去除重复镜头

5.1 将视频打散为图片

其中,vc=cv2.VideoCapture()

参数为0时,即vc=cv2.VideoCapture(0),表示打开笔记本的内置摄像头;

参数为视频文件路径,即vc=cv2.VideoCapture(“../testi.mp4”),为打开视频文件。

代码如下:

import os
import cv2
import subprocess

os.chdir(r'D:\pythonclass')#转到目录下
v_path='ghz.mp4'
image_save='./img'#新建一个文件夹用于放生成的图片

cap=cv2.VideoCapture(v_path)
frame_count=cap.get(cv2.CAP_PROP_FRAME_COUNT)#返回帧数
print(frame_count)

for i in range(int(frame_count)):
    _,img=cap.read()
    img=cv2.cvtColor(img,cv2.cv2.COLOR_BGR2GRAY) #cv2.COLOR_RGBGRAY  cv2.COLOR_BGR2GRAY
    #大写的都是常量
    cv2.imwrite('./img/image{}.jpg'.format(i),img)#把i传进{}中

效果如图:

 

5.2比较图像相似度

5.2.1 基于相等比较图像相似度

涉及函数:operator(标准运算符替代函数)

其中,会用到operator.eq(a,b)。

eq(a, b) 与 a == b 相同。

Operator其他功能参考:operator --- 标准运算符替代函数 — Python 3.10.0 文档

代码如下:

import operator
from PIL import Image
a=Image.open('./img/image0.jpg')
b=Image.open('./img/image0.jpg')
print(a)
out=operator.eq(a,b)
print(out)

5.2.2 基于numpy计算图片是否相等

涉及函数:NumPy 算术函数;any()函数。

①umpy包含简单的加减乘除: add(),subtract(),multiply() 和 divide()。

np.subtract(a,b)表示两个数组相减。

②any() 函数: iterable 中的任何一项为 true或可迭代对象为空,则 any() 函数返回 True,否则返回 False。

元素除了是 0、空、FALSE 外都算 TRUE。

代码如下:

import operator 
from PIL import Image
import os
os.chdir(r'D:\pythonclass')

a=Image.open('./img/image0.jpg')
b=Image.open('./img/image0.jpg')

out=operator.eq(a,b)
print(out)

5.2.3 基于哈希(以均值哈希算法为例)

基本原理:图片包含了不同频率的部分,其中,亮度变化小的是低频成分,反之为高频。低频成品描述的是大范围的信息,高频成片描述的是细节。小图缺乏细节,所以是低频的。

算法基本思路:

1.缩小图片尺寸为8*8

2.转为灰度图

3.计算像素的灰度平均值

4.基于灰度生成hash值

5.将图像分离为RGB三通道,计算每个通道的相似值

6.对比hash值(计算汉明距离,不同位数越少,图片相似度大)

哈希算法参考:哈希算法-图片相似度计算_chenghaoy的博客-CSDN博客_均值哈希算法

代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt
import os

#均值哈希算法
def aHash(img):
    #缩放为8*8
    plt.imshow(img)
    plt.axis('off')
    plt.show()
    img=cv2.resize(img,(8,8))
    plt.imshow(img)
    plt.axis('off')
    plt.show()
    
    #转换为灰度图
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    s=0
    hash_str='' # s为像素和初值为0,hash_str为hash值初值为''
    #遍历累加求像素和
    for i in range(8):
        for j in range(8):
            s=s + gray[i,j]
    #求平均灰度
    avg=s/64
    #灰度大于平均值为1  相反为0  生成图片的hash值
    for i in range(8):
        for j in range(8):
            if gray[i,j]>avg:
                hash_str=hash_str+'1'
            else:
                hash_str=hash_str+'0'
    return hash_str

# 通过得到RGB每个通道的直方图来计算相似度
def classify_hist_with_split(image1,image2,size=(256,256)):
    #将图像resize后,分离为RGB三个通道,再计算每个通道的相似值
    image1 = cv2.resize(image1,size)
    image2 = cv2.resize(image2,size)
    plt.imshow(image1)
    plt.show()
    plt.axis('off')
    
    plt.imshow(image2)
    plt.show()
    plt.axis('off')
    
    sub_image1=cv2.split(image1)
    sub_image2=cv2.split(image2)
    sub_data=0
    
    for im1,im2 in zip(sub_image1,sub_image2):
        sub_data+=calculate(im1,im2)
    sub_data=sub_data/3
    return sub_data

# 计算单通道的直方图的相似值
def calculate(image1,image2):
    hist1 = cv2.calcHist([image1],[0],None,[256],[0.0,225.0])
    hist2 = cv2.calcHist([image2],[0],None,[256],[0.0,225.0])
    plt.plot(hist1,color="r")
    plt.plot(hist2,color="g")
    plt.show()
    # 计算直方图的重合度
    degree = 0
    for i in range(len(hist1)):
        if hist1[i]!=hist2[i]:
            degree=degree+(1-abs(hist1[i])-hist2[i])/max(hist1[i],hist2[i])
        else:
            degree = degree + 1#统计相似
    degree = degree / len(hist1)
    return degree

# Hash值对比
def cmpHash(hash1,hash2):
    n=0
    print(hash1)
    print(hash2)
    # hash长度不同则返回-1代表传参出错
    if len(hash1)!=len(hash2):#!=不等于
        return -1
    #遍历判断
    for i in range(len(hash1)):
         # 不相等则n计数+1,n最终为相似度
        if hash1[i]!=hash2[i]:
            n=n+1
    return n

img1 = cv2.imread('./img/image0.jpg')
img2 = cv2.imread('./img/image1.jpg')

hash1 = aHash(img1)
hash2 = aHash(img2)
n=cmpHash(hash1,hash2)
print('均值哈希算法相似度:',n)

n=classify_hist_with_split(img1,img2)#看的是image0和image1
print('三直方图算法相似度:',n)

效果如图:

 

 

 

 

 

 

此外,还可以对分镜头进行比对,去除重复的镜头,将筛选后的图片置于一个文件夹中。

代码如下:

import os
import cv2
from PIL import Image
os.chdir(r'D:\pythonclass\video')
print(os.getcwd())

#for f in os.listdir('./shot'):
for i in range(549):
    img1 = cv2.imread('./img/image{}.jpg'.format(i))
    img2 = cv2.imread('./img/image{}.jpg'.format(i+1))
    hash1 = aHash(img1)
    hash2 = aHash(img2)
    n = cmpHash(hash1,hash2)
    if (n>32):#可通过改变参数,得到不同的镜头数
        print('均值哈希算法相似度:',n/64)
        cv2.imwrite('./shot/image{}.jpg'.format(i+1),img2)

效果如图:

 

 

5.3 视频截取:ffmpeg

运用ffmpeg截取1min的视频。

在程序框中输入:ffmpeg -i food.mp4 -ss 1 -t 60 -codec copy foodcut.mp4

将截取的视频命名为 原名cut.mp4

效果如图:

5.4 综合运用

在5.3基础上,运用5.1和5.2的方法对所截视频进行处理。

5.4.1练习一

代码如下:

效果如图:

标签:plt,hash,img,cv2,第五节,哈希,图像,import,分镜头
来源: https://blog.csdn.net/qq_61995860/article/details/120879812