需要安装:
pyqt5
pyqt5-tools
在终端中输入以下命令进行安装:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyqt5
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyqt5-tools
若想实现自行设计界面及将界面转换为python文件功能,可以安装好包后参考这篇博文进行配置:
https://www.cnblogs.com/lovesoo/p/12491361.html
实验所需数据集可从这里下载http://www.vision.caltech.edu/datasets/(需要科学上网)
下载到对应的人脸数据集后需要将图片从0-n重命名并修改代码中相关参数
若需要处理好后的数据集可私信我或从我上传的资源中下载:
数字图像处理Python+PyQt5实现基于CLD算法的人脸检测源码+数据集
image_org为人脸数据集存放位置
test2为CLD及相关算法函数实现
testUI3为PyQt5实现的界面代码及图像检索功能相关代码
# -*- coding: utf-8 -*-
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog, QApplication
import test2 as t2
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(775, 721)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton_openImage = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_openImage.setGeometry(QtCore.QRect(70, 260, 93, 28))
self.pushButton_openImage.setObjectName("pushButton_openImage")
self.label_image = QtWidgets.QLabel(self.centralwidget)
self.label_image.setGeometry(QtCore.QRect(200, 50, 321, 231))
self.label_image.setFrameShape(QtWidgets.QFrame.Box)
self.label_image.setObjectName("label_image")
self.label_image.setScaledContents(True) # 图片填充整个框
self.pushButton_saveImage = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_saveImage.setGeometry(QtCore.QRect(70, 350, 93, 28))
self.pushButton_saveImage.setObjectName("pushButton_saveImage")
self.label_txt = QtWidgets.QLabel(self.centralwidget)
self.label_txt.setGeometry(QtCore.QRect(200, 350, 321, 231))
self.label_txt.setFrameShape(QtWidgets.QFrame.Box)
self.label_txt.setObjectName("label_txt")
self.label_txt.setScaledContents(True) # 图片填充整个框
self.label_imagePath = QtWidgets.QLabel(self.centralwidget)
self.label_imagePath.setGeometry(QtCore.QRect(570, 60, 150,100))
self.label_imagePath.setObjectName("label_imagePath")
self.label_imagePath.setWordWrap(True)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 775, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.pushButton_openImage.clicked.connect(self.openImage)
self.pushButton_saveImage.clicked.connect(self.findImage)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton_openImage.setText(_translate("MainWindow", "上传图像"))
self.label_image.setText(_translate("MainWindow", "待检索图像"))
self.pushButton_saveImage.setText(_translate("MainWindow", "开始检索"))
# self.pushButton_openFile.setText(_translate("MainWindow", "打开文件"))
self.label_txt.setText(_translate("MainWindow", "检索到的图片(若找不到,显示“查无此人”)"))
self.label_imagePath.setText(_translate("MainWindow", "图片路径"))
def openImage(self): # 选择本地图片上传
global imgName # 这里为了方便别的地方引用图片路径,我们把它设置为全局变量
imgName, imgType = QFileDialog.getOpenFileName(self.centralwidget, "打开图片", "", "*.jpg;;*.png;;All Files(*)") # 弹出一个文件选择框,第一个返回值imgName记录选中的文件路径+文件名,第二个返回值imgType记录文件的类型
jpg = QtGui.QPixmap(imgName).scaled(self.label_image.width(), self.label_image.height()) # 通过文件路径获取图片文件,并设置图片长宽为label控件的长宽
self.label_image.setPixmap(jpg) # 在label控件上显示选择的图片
self.label_imagePath.setText(imgName) # 显示所选图片的本地路径
def findImage(self):
img = cv2.imread(imgName) # 这里就是读取0.jpg
img = cv2.resize(img, (256, 384))
CLD_img1 = t2.CLD(img) # 对img进行CLD处理
cld_index = []
cld_img = []
cld_class = []
cld_new_class = []
# {坐标:距离}
dict = {}
for i in range(0, 432):
img2 = cv2.imread('.\\image_org\\faces\\%d.jpg' % (i))
img2 = cv2.resize(img2, (256, 384))
CLD_img2 = t2.CLD(img2)
distances = t2.distance_CLD(CLD_img1, CLD_img2)
dict[i] = distances
dict_sorted = sorted(dict.items(), key=lambda kv: (kv[1], kv[0]))
print(dict_sorted)
print(type(dict_sorted)) # list
print(dict_sorted[0][0])
print(type(dict_sorted[0][0]))
img_out_index = str(dict_sorted[0][0])
if dict_sorted[0][1] >= 1200:
print("查无此人")
self.label_txt.setText("查无此人")
else:
img_path = './image_org/faces/' + img_out_index + '.jpg'
jpg = QtGui.QPixmap(img_path).scaled(self.label_image.width(),
self.label_image.height()) # 通过文件路径获取图片文件,并设置图片长宽为label控件的长宽
self.label_txt.setPixmap(jpg)
# def saveImage(self): # 保存图片到本地
# screen = QApplication.primaryScreen()
# pix = screen.grabWindow(self.label_image.winId())
# fd,type= QFileDialog.getSaveFileName(self.centralwidget, "保存图片", "", "*.jpg;;*.png;;All Files(*)")
# print(fd)
# # pix.save(fd)
# def openDirectory(self): # 打开文件夹(目录)
# fd = QFileDialog.getExistingDirectory(self.centralwidget, "选择文件夹", "")
# self.label_directoryPath.setText(fd)
# def openTextFile(self): # 选择文本文件上传
# fd,fp = QFileDialog.getOpenFileName(self.centralwidget, "选择文件", "", "*.txt;;All Files(*)")
# f=open(fd,'r')
# self.label_txt.setText(f.read())
# self.label_filePath.setText(fd)
# f.close()
# def saveTextFile(self): # 保存文本文件
# fd,fp= QFileDialog.getSaveFileName(self.centralwidget, "保存文件", "", "*.txt;;All Files(*)")
# f=open(fd,'w')
# f.write(self.label_txt.text())
# f.close()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
formObj = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(formObj)
formObj.show()
sys.exit(app.exec_())
# coding: utf-8
# In[1]:
import cv2
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.fftpack import dct
import redis
# In[2]:
def cvshow(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# In[3]:
def CLD(img):
# 图像分割8*8
n = 8
(height, width, channel) = img.shape
# print(height,width,channel) #384 256 3
block_h = np.fix(height / n) # 每块的高度
block_w = np.fix(width / n) # 每块的宽度
# print(block_h,block_w) # 48.0 32.0
im_n = np.zeros((n, n, channel))
for i in range(n):
for j in range(n):
for k in range(channel):
# 确定块
a = block_h * i + 1
b = block_h * (i + 1) # height: b-a
c = block_w * j + 1
d = block_w * (j + 1) # width: d-c
# 循环到右下角的块时
if i == (n - 1):
b = height - 1
if j == (n - 1):
d = width - 1
# 每块代表色的选择,实现“mpeg-7标准推荐使用区域块的平均像素颜色值作为代表颜色”
# print(img[int(a)][int(d)][int(k)])
arr = [img[int(a)][int(c)][k], img[int(a)][int(d)][k], img[int(b)][int(c)][k], img[int(b)][int(d)][k]]
pix = np.mean(np.mean(arr));
# print(pix)
im_n[i][j][k] = pix
# print(im_n)
# 将rgb转换色彩空间为YCbCr
mat = np.array(
[[65.481, 128.553, 24.966],
[-37.797, -74.203, 112.0],
[112.0, -93.786, -18.214]])
offset = np.array([16, 128, 128])
# rgb2ycbcr():颜色空间转换的函数
im_YCbCr = rgb2ycbcr(mat, offset, im_n)
# DCT变换
im_DCT = np.zeros((n, n, channel));
# 因为dct操作只能对二维矩阵进行操作,所以这里要把r,g,b分别拎出来处理
im_DCT[:, :, 0] = dct(im_YCbCr[:, :, 0])
im_DCT[:, :, 1] = dct(im_YCbCr[:, :, 1])
im_DCT[:, :, 2] = dct(im_YCbCr[:, :, 2])
# print(im_DCT)
# 按照之字形扫描im_DCT存储到descript中
zig = [[0, 1, 5, 6, 14, 15, 27, 28],
[2, 4, 7, 13, 16, 26, 29, 42],
[3, 8, 12, 17, 25, 30, 41, 43],
[9, 11, 18, 24, 31, 40, 44, 53],
[10, 19, 23, 32, 39, 45, 52, 54],
[20, 22, 33, 38, 46, 51, 55, 60],
[21, 34, 37, 47, 50, 56, 59, 61],
[35, 36, 48, 49, 57, 58, 62, 63]]
descript = np.zeros((n * n, channel));
for i in range(n):
for j in range(n):
descript[zig[i][j], :] = im_DCT[i, j, :];
# print(descript);
result = descript;
return result;
# In[4]:
# 颜色空间转换的函数
def rgb2ycbcr(mat, offset, rgb_img):
n = 8
channel = 3
ycbcr_img = np.zeros((n, n, channel))
for x in range(n):
for y in range(n):
ycbcr_img[x, y, :] = np.round(np.dot(mat, rgb_img[x, y, :] * 1.0 / 255) + offset)
return ycbcr_img
# In[5]:
def distance_CLD(img1, img2):
return np.sqrt(np.sum(np.square(img1 - img2))) # 欧式距离
# In[6]:
def drawline(recall, precision):
plt.plot(recall, precision)
plt.xlabel("recall")
plt.ylabel("precision")
plt.title('PR Graph of CLD')
plt.show()
# In[7]:
if __name__ == "__main__":
img_index = 60; # 设置样本img的编号
img = cv2.imread('./image_org/faces/' + str(img_index) + '.jpg') # 这里就是读取0.jpg
CLD_img1 = CLD(img) # 对img进行CLD处理
cld_index = []
cld_img = []
cld_class = []
cld_new_class = []
# {坐标:距离}
dict = {}
for i in range(0, 432):
img2 = cv2.imread('.\\image_org\\faces\\%d.jpg' % (i))
img2 = cv2.resize(img2, (256, 384))
CLD_img2 = CLD(img2)
distances = distance_CLD(CLD_img1, CLD_img2)
dict[i] = distances
dict_sorted = sorted(dict.items(), key=lambda kv: (kv[1], kv[0]))
print(dict_sorted)
print(type(dict_sorted)) # list
print(dict_sorted[0][0])
print(type(dict_sorted[0][0]))
img_out_index = str(dict_sorted[0][0])
if dict_sorted[0][1]>=1200:
print("查无此人")
else:
img_out = cv2.imread('./image_org/faces/' + img_out_index + '.jpg')
cvshow("img",img_out)
描述:上传一张存在于数据库中的人物的图像(上传的图片在数据库中没有完全相同的对应图像,只有与其相似的数张图像),检索后返回一张与上传图片最像(两者“距离”最小)的图片,表示在数据库中成功检索到该人物
样例一:
上传图片后界面显示:
点击“开始检索”后界面:
可以看到成功检索到了该人物
样例二:
样例三:
可以看到都成功检索到了对应人物的图像
描述:上传一张不存在于数据库中的人物的图像,检索后若找不到则会显示“查无此人”,表示在数据库中检索不到该人物(本程序中阈值设置为1200,即通过计算后上传的图片与数据库中图片的最小距离若大于 1200,则认为该上传图像对应的人物不存在于数据库中,显示“查无此人”)
样例一:
上传图片后界面:
点击“开始检索”后界面:
可以看到在数据集中检索不到该人物,从控制台中输出可以看到上传的该图像与数据集中图像间最小“距离”大于阈值1200,因此判定为“检索不到”,显示“查无此人”
样例二:
pyqt5:利用QFileDialog从本地选择图片\文本文档显示到label、保存图片\label文本到本地(附代码)
图像特征提取算法:颜色布局描述符Color Layout Descriptor
计算机视觉 实验四 分别使用颜色布局描述符(Color Layout Descriptor)与方向梯度直方图(HOG)实现图像检索,并且画出图像的PR曲线图
本文章相关源代码与处理好的人脸数据集:数字图像处理Python+PyQt5实现基于CLD算法的人脸检测源码+数据集