目录
一、基础环境配置
(一)Pycharm安装及配置
在官网下载社区版的Pycharm,并安装。
安装时,尽量安装在纯英文目录下,防止后续使用中出现问题。
(二)新建项目
在Pycharm中新建项目,路径也尽量选择纯英文路径,并在新建菜单栏中选中下图中标红的两项。由于之前一直使用的是IDLE(Python 3.9)版本进行编译,选中这两项后,可以直接将之前安装的第三方库在Pycharm中使用,减少了重新安装第三方库的繁琐。
(三)配置资源环境
将程序所需的视频、图片、HTML文件放置到程序的相同目录下,可以省去修改路径的步骤。
二、 Flask基本操作
(一)检验Flask运行状态
在程序中输入下列代码:
from flask import Flask
#导入带三方库
app = Flask(__name__)
#定义app
@app.route('/')
def hello_world():
return 'Hello, World!'
#定义待输出内容
if "__main__"==__name__:
app.run(port="5008")
#运行
运行结果如下:
证明Flask运行正常。
(二)渲染网页
1、设置网页格式
在程序所在的目录下创建一个文件夹,命名为“templates”。在该文件夹下,新建HTML文件,并命名为“index.html”,编辑内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Flask分镜</title>
</head>
<body>
视频分镜
</body>
</html>
2、利用程序向网页中写入内容
代码如下:
from flask import Flask,render_template
app=Flask(__name__)
@app.route('/')
def index():
#return "Hi,Flask!"
return render_template('index.html')
if "__main__"==__name__:
app.run(port="5008")
运行程序,结果如下:
渲染网页成功。
三、利用Flask实现分镜
(一)利用程序将视频逐帧导出为图片,并呈现到前端
1、配置前端格式
在程序所在的目录下创建一个文件夹,命名为“templates”。在该文件夹下,新建HTML文件,并命名为“index.html”,编辑内容如下:
<body>
视频分镜
<br>
<video width="640" height="480" controls autoplay>
<source src="static/hy.mp4" type="video/mp4">
<object data="static/hy.mp4" width="640" height="480">
<embed width="640" height="480" src="static/hy.mp4">
</object>
</video>
<br>
帧数:{{framecount}}<br>
{% for i in range(framecount) %}
<img height="20" src="{{pic1}}{{i}}.jpg" />
{% endfor %}
</body>
显示格式为:
2、编写程序
代码如下:
from flask import Flask,render_template
import os
import cv2
#导入第三方库
app=Flask(__name__)
def genFrame():
#将已有视频逐帧导出为图片
v_path='static/hy.mp4'
image_save='static/pic'
#读取文件
if not(os.path.exists(image_save)):
os.mkdir(image_save)
cap=cv2.VideoCapture(v_path)
fc=cap.get(cv2.CAP_PROP_FRAME_COUNT)
for i in range(int(fc)):
_,img=cap.read()
cv2.imwrite('static/pic/image{}.jpg'.format(i),img)
@app.route('/')
def index():
#return "Hi,Flask!"
genFrame()
#将已有视频逐帧导出为图片
pic='static/pic/image'
framecount=470
return render_template('index.html',pic1=pic,framecount=framecount)
if "__main__"==__name__:
app.run(port="5008")
输出的结果为:
(二)通过哈希值比较及图像直方图统计实现分镜
1、设置网页格式
代码如下:
<body>
视频分镜
<br>
<video width="640" height="480" controls autoplay>
<source src="static/hy.mp4" type="video/mp4">
<object data="static/hy.mp4" width="640" height="480">
<embed width="640" height="480" src="static/hy.mp4">
</object>
</video>
<br>
均值哈希帧数:{{framecount}}<br>
{% for i in range(framecount) %}
<img height="40" src="static/hash/{{filename[i]}}" />
{{filename[i]}}
{% endfor %}
<br>
直方图相似度帧数:{{histcount}}<br>
{% for i in range(histcount) %}
<img height="40" src="static/hist/{{histfile[i]}}" />
{{histfile[i]}}
{% endfor %}
</body>
网页格式如下:
2、代码实现
导入第三方库并定义app
import os
import numpy as np
import matplotlib.pyplot as plt
from flask import Flask,render_template
from PIL import Image
app=Flask(__name__)
定义计算序列中相邻图片的哈希值函数
def aHash(img):
#计算图像的哈希值
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
#求平均灰度
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
#灰度大于平均值为1,小于平均值为0,生成图片的hash值
定义哈希值对比函数
def cmpHash(hash1,hash2):
#将哈希值进行对比
n = 0
#print(hash1)
#print(hash2)
if len(hash1)!=len(hash2):
return -1
#hash长度不同则返回-1,代表传参出错
for i in range(len(hash1)):
#遍历判断
if hash1[i] != hash2[i]:
n = n + 1
return n
#不相等则n计数+1,n最终为相似度
将通过哈希值识别出的不同分镜图片存入文件中
img0 = cv2.imread('./static/pic/image{}.jpg'.format(0))
cv2.imwrite('./static/hash/image{}.jpg'.format(0),img0)
#保留第一帧画面
for i in range(469):
img1 = cv2.imread('./static/pic/image{}.jpg'.format(i))
img2 = cv2.imread('./static/pic/image{}.jpg'.format(i + 1))
# 按序读入图片序列
hash1 = aHash(img1)
hash2 = aHash(img2)
n = cmpHash(hash1, hash2)
if (n > 30):
#print("均值哈希算法相似度:", n / 64)
cv2.imwrite('./static/hash/image{}.jpg'.format(i + 1), img2)
定义计算序列中相邻图片的图像直方图函数
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
# 返回结果
制定判断精准度,并将通过直方图得出的不同分镜图片存入文件中
img0 = cv2.imread('./static/pic/image{}.jpg'.format(0))
cv2.imwrite('./static/hist/image{}.jpg'.format(0),img0)
#保留第一帧画面
for i in range(469):
img1=cv2.imread('./static/pic/image{}.jpg'.format(i))
img2=cv2.imread('./static/pic/image{}.jpg'.format(i+1))
#按序读入图片序列
n=calculate(img1,img2)
#n2=为单通道直方图相似度
if (n<0.67):
cv2.imwrite('./static/hist/image{}.jpg'.format(i+1),img2)
#保存符合条件的图片
将图片按照已有的目标网页导入前端
@app.route('/')
def shot():
path='static/hash'
filename = os.listdir(path)
framecount=len(filename)
filename.sort(key= lambda x:int(x[5:-4]))
path='static/hist'
histfile = os.listdir(path)
histcount=len(histfile)
histfile.sort(key= lambda x:int(x[5:-4])) #对List的元素排序
return render_template('shot.html',filename=filename,framecount=framecount,histfile=histfile,histcount=histcount)
if "__main__"==__name__:
app.run(port="5008")
输出结果为:
四、总结
编写程序一定要把握各个细节,一个小小的问题就会让整个程序无法运行。例如,在第三部分中,因为“for···in···”循环中的图片序列数多了一张,导致程序一直报错,无法找到相关文件。直到从头到尾检查了一遍,才找出问题所在。