赞
踩
使用感知哈希方法,进行缩略图比较,来判断图像的相似度
先把目录下的所有图片都读取出来,再进行判断
优点:速度快
缺点:获取所有图像的指纹需要较多内存和时间来进行处理
- #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;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。