任务
在windows10系统下,通过代码编辑器PyCharm写入python程序,构建flask框架实现web端查看。将通过均值哈希算法或各通道直方图相似度计算完成视频分帧、分镜(week6已完成)迁移至web端显示;利用Scipy-kmeans对图片进行聚类色彩提取。
目录
Ⅰ均值哈希算法
?Ⅱ各通道直方图相似度计算
??ⅢScipy-kmeans聚类
?Ⅳ聚类色彩提取
Ⅰ均值哈希算法
py文件:
导入所需各库,实例化flask对象,定义均值哈希算法的函数,得出相似度指数。
from flask import Flask, render_template
import os
import cv2
app = Flask(__name__)
def aHash(img):
img = cv2.resize(img, (8, 8))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
s = 0
hash_str = ""
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
def cmpHash(hash1, hash2):
gap = 0
if len(hash1) != len(hash2):
return -1
for i in range(len(hash1)):
if hash1[i] != hash2[i]:
gap = gap + 1
similar=1-gap/64
return similar
定义函数:对视频分帧,保存所有图片,对保存的图片依次(非相邻图片,而是以上一次临界图片为中心,遍历所有图片)进行均值哈希算法比对相似度,保存差异巨大的图片,从而得出视频分镜。
离线计算出视频分镜的结果,即在web端请求访问前就运算好。
def genFrame():
v_path="static/video.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)
filelist = os.listdir("static/pic")
img1=cv2.imread("static/pic/image0.jpg")
cv2.imwrite(os.path.join("static/p", filelist[0]), img1)
for i in range(len(filelist) - 1):
img2 = cv2.imread("static/pic/" + "image{}".format(i + 1) + ".jpg")
sim = cmpHash(aHash(img1), aHash(img2))
if sim < 0.4:
cv2.imwrite(os.path.join("static/p", "image{}".format(i + 1) + ".jpg"), img2)
img1 = cv2.imread("static/pic/" + "image{}".format(i + 1) + ".jpg")
genFrame()
定义web端要展示的相关内容,同名映射到html文件里,运行程序。
@app.route("/")
def index():
filelist=os.listdir("static/p")
count=int(len(filelist))
pic="static/p/"
title="hash"
return render_template("hash.html",pic=pic,filelist=filelist,count=count,title=title)
if "__main__"==__name__:
app.run()
?html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
</head>
<body>
<br>
视频
<video width="640" height="480" controls autoplay>
<source src="static/video.mp4" type="video/mp4">
<object data = "static/video.mp4" width = "640" height = "480" >
<embed width = "640" height = "480" src = "static/video.mp4" >
</object>
</video>
<br>
视频镜头数:{{count}}
<br>
{% for i in range(count) %}
<img height="40" src="{{pic}}{{ filelist[i]}}"/>
{% endfor %}
</body>
</html>
运行结果:
?
?Ⅱ各通道直方图相似度计算
?py文件:
from flask import Flask, render_template
import os
import cv2
import numpy as np
import shutil
app = Flask(__name__)
# 计算单通道的直方图的相似值
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])
# 计算直方图的重合度
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
# 分离出RGB每个通道,分别计算直方图来相似度,求均值
def classify_hist_with_split(image1, image2, size=(256, 256)):
image1 = cv2.resize(image1, size)
image2 = cv2.resize(image2, size)
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 genFrame():
v_path="static/video.mp4"
image_save="static/pic1"
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/pic1/image{}.jpg".format(i),img)
filelist = os.listdir("static/pic1")
img1=cv2.imread("static/pic1/image0.jpg")
cv2.imwrite(os.path.join("static/pp", filelist[0]), img1)
for i in range(len(filelist) - 1):
img2 = cv2.imread("static/pic1/" + "image{}".format(i + 1) + ".jpg")
sim = classify_hist_with_split(img1, img2)
if sim < 0.42:
cv2.imwrite(os.path.join("static/pp", "image{}".format(i + 1) + ".jpg"), img2)
img1 = cv2.imread("static/pic1/" + "image{}".format(i + 1) + ".jpg")
genFrame()
@app.route("/")
def index():
filelist=os.listdir("static/pp")
count=int(len(filelist))
pic="static/pp/"
title="histogram"
return render_template("hash.html",pic=pic,filelist=filelist,count=count,title=title)
if "__main__"==__name__:
app.run()
html文件:同均值哈希算法中的html文件
运行结果:
?ⅢScipy-kmeans聚类
iter是显示每次迭代结果。off是不显示迭代结果。final是显示最终迭代结果。
idx = kmeans(X,k) 执行 k 均值聚类,以将 n×p 数据矩阵 X 的观测值划分为 k 个聚类,并返回包含每个观测值的簇索引的 n×1 向量 (idx)。X 的行对应于点,列对应于变量。默认情况下,kmeans 使用欧几里德距离平方度量,并用 k-means++ 算法进行簇中心初始化。
np.array[:,1]表示取这个array数组所有行的第二列数据,逗号左边控制行的范围,右边控制列的范围 plt.scatter(x,y,c)分别定义横纵坐标和颜色
import numpy as np
from scipy.cluster.vq import vq, kmeans, whiten
import matplotlib.pyplot as plt
fe = np.array([[1.9,2.0],
[1.7,2.5],
[1.6,3.1],
[0.1,0.1],
[0.8,0.3],
[0.4,0.3],
[0.22,0.1],
[0.4, 0.3],
[0.4,0.5],
[1.8,1.9]])
book = np.array((fe[0], fe[1]))
print(type(book))
print("book: \n",book)
codebook, distortion = kmeans(fe, book)#book定义了初始聚类中心的位置和个数
#codebook,distortion = kmeans(fe,n)#n定义了聚类中心的个数,同时启用iter参数
print("codebook:", codebook)
print("distortion: ", distortion)
plt.scatter(fe[:,0], fe[:,1], c='g')#所有点的散点图
plt.scatter(codebook[:, 0], codebook[:, 1], c='r')#聚类中心散点图
plt.show()
运行结果:?
?Ⅳ聚类色彩提取
py文件:
thumbnail((x,y))转换为一定大小的缩略图
from flask import Flask, render_template
from PIL import Image
import numpy as np
from scipy.cluster.vq import kmeans
app = Flask(__name__)
#用缩略图聚类
def colorz(filename,n=3):
img=Image.open(filename)
img=img.rotate(-90)#顺时针旋转90°
img.thumbnail((200,200))#x,y必须一样大
w,h=img.size
points=[]
for count,color in img.getcolors(w*h):
points.append(color)
return points
#对色彩聚类
def kmeansColor(img,n):
points=colorz(img,3)
fe = np.array(points,dtype=float) #聚类需要是Float或者Double
codebook, distortion = kmeans(fe,n) #7是聚类中心个数
centers=np.array(codebook,dtype=int) #由float浮点数转为integer整型
return centers
@app.route("/")
def index():
imgcolors=kmeansColor("static/bargain.jpg",3)
return render_template("spicy.html",imgcolors=imgcolors)
if "__main__"==__name__:
app.run(port="5008")
?html文件:
将图片中聚类后的色彩提取出来的三类颜色分别赋于文字“颜色”上
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>spicy</title>
</head>
<body>
<img height="400" src='static/bargain.jpg'>
<br>
{{imgcolors}}<br>
{% for c in imgcolors %}
<font style="color:rgb({{c[0]}},{{c[1]}},{{c[2]}}">颜色</font>
{% endfor %}
</body>
</html>
?运行结果:
?
|