-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathsim_hash.cpp
131 lines (123 loc) · 3.69 KB
/
sim_hash.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <iostream>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
//使用感知哈希算法进行图片去重
//构建一个结构体,用于存储对应名称和要比较的内容
typedef struct MatStruct{
string name;
unsigned char buf[64];
MatStruct(){
name = "";
memset(buf, 0, 64);
}
MatStruct(const struct MatStruct &ms){
name = ms.name;
memset(buf, 0, 64);
memcpy(buf, ms.buf, 64);
}
//重载比较函数
bool operator<(const struct MatStruct &ms)const {
return name < ms.name;
}
}MatStruct;
int getdirimages(string path, std::vector<MatStruct> &images)
{
std::vector<MatStruct> tmpimages;
DIR *dir;
struct dirent *ptr;
dir = opendir(path.c_str());
while((ptr = readdir(dir)) != NULL) {
if((strcmp(ptr->d_name,".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
continue;
}
string fullname = path + "/" + ptr->d_name;
Mat img = imread(fullname);
if(img.empty()){
continue;
}
MatStruct ms;
ms.name = ptr->d_name;
Mat gray, res;
//缩放成8x8大小灰度图
resize(img, res, Size(8,8));
cvtColor(res, gray, CV_BGR2GRAY);
//获取灰度平均值
double mn = mean(gray)[0];
//比较像素灰度,获取图像指纹
for(int i = 0; i < 8; i++){
for(int j = 0; j < 8; j++){
ms.buf[i*8 + j] = (gray.at<unsigned char>(i,j) > mn) ? 1 : 0;
}
}
cout << "get " << fullname << endl;
tmpimages.push_back(ms);
}
closedir(dir);
std::sort(tmpimages.begin(), tmpimages.end());
tmpimages.swap(images);
}
int main(int argc, char* argv[])
{
if(argc <= 1){
cout << argv[0] << " picpath" << endl;
return -1;
}
struct stat st;
if(stat(argv[1], &st) != 0 || (st.st_mode & S_IFDIR) != S_IFDIR){
cout << argv[1] << " is not dir" << endl;
return -1;
}
int startpos = 0;
int curpos = 0;
std::vector<MatStruct> images;
cout << "start getdir" << endl;
getdirimages(argv[1], images);
cout << "start compare" << endl;
std::vector<MatStruct>::iterator it1 = images.begin();
while(it1 != images.end()){
std::vector<MatStruct>::iterator it2 = it1;
curpos = 0;
//存储需要删除的迭代对象
std::vector<std::vector<MatStruct>::iterator> delImages;
cout << it1->name << endl;
while(it2 != images.end()){
int diff = 0;
if(it2 == it1){
it2++;
continue;
}
//比较两个图片的相似度,不同的地方不超过5,则为相似的图片
for(int i = 0; i < 64; i++){
if(it1->buf[i] != it2->buf[i]){
diff++;
}
}
if(diff < 5){
delImages.push_back(it2);
}
it2++;
}
if(delImages.size() > 0){
//删除图像
for(int i = 0; i < delImages.size(); i++){
cout << "remove " << delImages[i]->name << endl;
string fullpath = string(argv[1]) + "/" + delImages[i]->name;
unlink(fullpath.c_str());
images.erase(delImages[i]);
}
it1 = images.begin();
for(int index = 0; index < startpos; index++)
it1++;
continue;
}
startpos++;
it1++;
}
return 0;
}