目录
一、图像直方图
完整代码:
运行结果:
函数使用:
二、视频分镜
1、基于均值哈希
运行结果:
完整代码:
2、基于直方图相似度
运行结果:
完整代码:
三、截取视频(1分钟)
完整代码:
参数含义:
问题记录:
一、图像直方图
完整代码:
import cv2
import matplotlib.pyplot as plt
img= cv2.imread("girl.png")
histb = cv2.calcHist([img], [0], None, [256], [0, 255])
histg = cv2.calcHist([img], [1], None, [256], [0, 255])
histr = cv2.calcHist([img], [2], None, [256], [0, 255])
print(type(histb))
print(histb.size)
print(histb.shape)
plt.plot(histb, color="b")
plt.plot(histg, color="g")
plt.plot(histr, color="r")
plt.show()
运行结果:
函数使用:
cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]]) ->hist
imaes 输入的图像,要带[]号
channels 选择图像的通道,012对应着BGR,要带[]号
mask 掩膜,是一个大小和image一样的np数组,其中把需要处理的部分指定为1,不需要处理的部分指定为0,一般设置为None,表示处理整幅图像
histSize 灰度级的个数,使用多少个bin,一般为256,要带[]号
ranges 像素值的范围,一般为[0,255],要带[]号
二、视频分镜
(人工分镜结果)
1、基于均值哈希 运行结果:
(少识别了两个分镜头,误识别了三个分镜头)
完整代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 均值哈希算法
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为hash值初值为''
s = 0
hash_str = ''
# 遍历累加求像素和
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
# 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
for i in range(549):
img1=cv2.imread('./pic2/image{}.jpg'.format(i))
img2=cv2.imread('./pic2/image{}.jpg'.format(i+1))
hash1 = aHash(img1)
hash2 = aHash(img2)
n = cmpHash(hash1, hash2)
if(n>22):
print('均值哈希算法相似度:', n/64)
cv2.imwrite('./shot/image{}.jpg'.format(i+1),img2)
2、基于直方图相似度
运行结果:
(少识别了两个分镜头)
完整代码:import cv2
import numpy as np
import matplotlib.pyplot as plt
# 通过得到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) #cv2.split()拆分通道
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, 255.0])
hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.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
for i in range(549):
img1=cv2.imread('./pic2/image{}.jpg'.format(i))
img2=cv2.imread('./pic2/image{}.jpg'.format(i+1))
n = classify_hist_with_split(img1,img2)
if(n<0.6):
cv2.imwrite('./shot2/image{}.jpg'.format(i+1),img2)
三、截取视频(1分钟) 完整代码:
截取视频前一分钟:
ffmpeg -i input.mp4 -vcodec copy -acodec copy -ss 00:00:00 -to 00:01:00 cut.mp4 -y
截取视频中间一分钟:
ffmpeg -i input.mp4 -vcodec copy -acodec copy -ss 00:00:05 -t 00:01:00 cut.mp4 -y
或ffmpeg -i input.mp4 -ss 5 -c copy -t 60 cut.mp4 -y
参数含义:
-to 截到视频的哪个时间点结束
-t 表示截取多长的时间
-vcodec copy 表示使用跟原视频一样的视频编解码器
-acodec copy 表示使用跟原视频一样的音频编解码器
问题记录:
-to 截到视频的哪个时间点结束
-t 表示截取多长的时间
-vcodec copy 表示使用跟原视频一样的视频编解码器
-acodec copy 表示使用跟原视频一样的音频编解码器
ffmpeg 为了加速,会使用关键帧技术(-ss 选项放在 -i 之前时), 有时剪切出来的结果在起止时间上未必准确,解决方法:ffmpeg -ss 00:01:00 -i video.mp4 -to 00:02:00 -c copy -copyts cut.mp4



