我有以下代码:
指纹.cpp:
#include <iostream>
#include <filesystem>
#include "ImageHash.h"
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include <opencv2/imgcodecs.hpp>
using namespace std;
void usage (char** argv) noexcept {
cout << "Usage: " << argv[0] << " <image or dir>" << endl << "Example: " << argv[0] << " template.png" << endl;
}
int main(int argc, char** argv) {
if (argc != 2) {
usage(argv);
return 1;
}
auto imgHash = ImageHash();
if (std::filesystem::is_directory(argv[1])) {
for (const auto& dirEntry : std::filesystem::recursive_directory_iterator(argv[1])) {
auto filePath = dirEntry.path();
std::string fileName = dirEntry.path().filename().string();
cv::Mat img = cv::imread(filePath.string(), cv::IMREAD_GRAYSCALE);
img.resize(8*8);
/*cv::imshow("img", img);
cv::waitKey();*/
cout << fileName << "\t\t" << imgHash.getHashString(img) << endl;
}
}
else if (std::filesystem::is_regular_file(argv[1])){
cv::Mat img = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);
cout << std::filesystem::path(argv[1]).filename().string() << "\t\t" << imgHash.getHashString(img) << endl;
}
else {
usage(argv);
}
return 0;
}
ImageHash.cpp:
#include "ImageHash.h"
#include <iomanip>
using namespace std;
ImageHash::ImageHash()
{
pHash = cv::img_hash::PHash::create();
}
std::string ImageHash::convertHashToString(vector<bool> hash) {
std::string ret = "";
double h = 0;
for (unsigned int i = 0; i < hash.size(); i++) {
if (hash[i]) {
h += pow(2, (i % 8));
}
if (i % 8 == 7) {
std::stringstream buffer;
buffer << std::hex << std::setfill('0') << std::setw(2) << h;
ret += buffer.str();
h = 0;
}
}
return ret;
}
std::vector<bool> ImageHash::hex_str_to_hash(std::string inputString) {
std::vector<bool> hash;
size_t size = inputString.size() / 2;
for (int i = 0; i < size; i++) {
std::string str2 = inputString.substr(i * 2, 2);
if (str2.empty()) {
continue;
}
unsigned int value = 0;
std::stringstream SS(str2);
SS >> std::hex >> value;
for (int j = 0; j < 8; j++) {
bool check = !!((value >> j) & 1);
hash.push_back(check);
}
}
return hash;
}
std::vector<bool> ImageHash::matHashToBoolArr(cv::Mat const inHash) {
const unsigned char* data = inHash.data;
std::vector<bool> v;
for (int i = 0; i < 8; i++) {
unsigned char c = data[i];
for (int j = 0; j < 8; j++) {
int shift = (8 - j) - 1;
bool val = ((c >> shift) & 1);
v.push_back(val);
}
}
return v;
}
std::vector<bool> ImageHash::computeHash(cv::Mat const input) {
cv::Mat inHash;
pHash->compute(input, inHash);
return matHashToBoolArr(inHash);
}
std::string ImageHash::getHashString(cv::Mat const input) {
return convertHashToString(computeHash(input));
}
//returns hamming distance
int ImageHash::getHashDistance(std::vector<bool>& hash1, std::vector<bool>& hash2) {
//assert(hash1.size() == hash2.size());
/* ToDo: I don't know why the size is not the same but if if is lets add padding to the smaller one
This does not seem to make it work*/
if (hash1.size() != hash2.size()) {
auto smaller = hash1.size() < hash2.size() ? &hash1 : &hash2;
auto larger = hash1.size() < hash2.size() ? hash2 : hash1;
smaller->resize(larger.size());
std::fill(begin(*smaller) + larger.size(), end(*smaller), 0);
}
int dist = 0;
for (unsigned int i = 0; i < hash1.size(); i++) {
dist += (hash1[i] != hash2[i]);
}
return dist;
}
由于某种原因,返回的哈希值根据输入图像具有不同的大小。我尝试在 getHashDistance() 处添加一些填充,但我认为我不应该这样做,因为现在当我计算两个相似图像之间的距离时,我得到一个很大的距离,就好像它们不相似一样。
你知道这是为什么吗?我正在将图像的大小调整为 8*8 img.resize(8*8);
,虽然它会成功,但它不起作用。
谢谢,谢谢