openCV中利用感知哈希算法是实现图片相似度计算
1、我们还是使用之前人脸识别检测案例中保存的人脸图像进行图像的识别比对
确定人脸图像痕斤保存的路径,在程序读取这些图片进行人脸相似度对比
图像库保存路劲:f:\mm\1
2、使用均值/pHash哈希值方法计算人脸图像相似度,主要实现思路:
1)从本地读取两张人脸图像
2)计算两张图片的均值哈希值/pHash哈希值
3)计算两张图片均值哈希值/pHash哈希值的汉明距离
4)判断相似度值:汉明距离越小说明两张图片互游侨越相似
3、使用均值哈哈希法计算图像的哈希值:
//计算图像的均值哈希值
string imgHashValue(Mat &img)
{
string rst(64, '\0');
//图片转灰
Mat ¥tmpImg;
if (img.channels() == 3) {
cvtColor(img, tmpImg, CV_BGR2GRAY);
}
else
{
tmpImg = img.clone();
}
//缩小图片尺寸,到64个像素
resize(tmpImg, tmpImg, Size(8, 8));
//简化色彩,转为256/4=64灰¥度
uchar *pData;
for (int i = 0; i < tmpImg.rows; i++)
{
//获取像素值
pData = tmpImg.ptr<uchar>(i);
for (int j = 0; j < tmpImg.cols; j++)
{
pData[j] = pData[j] / 4;
}
}
//计算所有像素的均值
int avergeValue = mean(tmpImg).val[0];
//比较像素的灰度值
//将每个像毙屈素的值与平均值比较,大于或等于平均值的标记为1,小于的标记为0,作为图像掩码
Mat mask = (tmpImg >= (uchar)avergeValue);
//计算hash值
int index = 0;
for (int i = 0; i < mask.rows; i++)
{
pData = mask.ptr<uchar>(i);
for (int j = 0; j < mask.cols; j++)
{
if (pData[j] == 0)
{
rst[index++] = '0';
}
else
{
rst[index++] = '1';
}
}
}
return rst;
}
4、使用pHash方法计算图片哈希值:
string pHashValue(Mat &srcImg)
{
Mat img, dstImg;
string rst(64, '\0');
double dIndex[64];
double mean = 0.0;
int k = 0;
cvtColor(srcImg, srcImg, CV_BGR2GRAY);
img = Mat_<double>(srcImg);
//缩放尺寸
resize(img, img, Size(8, 8));
//离散余弦变换 DCT
dct(img, dstImg);
//获取dct系数均值
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
dIndex[k] = dstImg.at<double>(i, j);
//计算每个像素的均值
mean += dstImg.at<double>(i, j) / 64;
++k;
}
}
//计算hash
for (int i = 0; i < 64; ++i)
{
if (dIndex[i] >= mean)
{
rst[i] = '1';
}
else {
rst[i] = '0';
}
}
return rst;
}
5、计算哈希值字符串的汉明距离:
//汉明距离计算:如果小于5怎可以认为两个图像时相似的
int hanmingDist(string &str1, string &str2)
{
if ((str1.size() != 64) || (str2.size() != 64))
{
return -1;
}
int distValue = 0;
for (int i = 0; i < 64; i++)
{
if (str1[i] != str2[i])
{
distValue++;
}
}
return distValue;
}
6、创建main函数,加载图片、计算哈希值、计算汉明距离:
int main()
{
Mat orgImg = imread("F:\\mm\\1\\img-1.jpg");
Mat img = imread("F:\\mm\\1\\img-2.jpg");
imshow("OrgImg", orgImg);
imshow("Img", img);
string str1 = imgHashValue(orgImg);
string str2 = imgHashValue(img);
int distance = hanmingDist(str1, str2);
cout << "两张图片的汉明距离:" << distance << endl;
if (distance < 5) {
cout << "两张图片相似" << endl;
}
else
{
cout << "两张图片不相似" << endl;
}
str1 = pHashValue(orgImg);
str2 = pHashValue(img);
distance = hanmingDist(str1, str2);
cout << "pHash两张图片的汉明距离:" << distance << endl;
if (distance < 5) {
cout << "两张图片相似" << endl;
}
else
{
cout << "两张图片不相似" << endl;
}
waitKey(0);
return 0;
}
7、运行程序进行图片相似度测试,汉明距离如果大于10可以认为两只图片不相似。从测试结果看,均值哈希法比pHash法准确度高。