Переглянути джерело

new: SimilaritySearch::findSimilarImages()

Satoshi Yoneda 2 тижнів тому
батько
коміт
f0d0108a03
3 змінених файлів з 27 додано та 46 видалено
  1. 2 0
      include/SimilaritySearch.hpp
  2. 8 46
      src/MainWindow.cpp
  3. 17 0
      src/SimilaritySearch.cpp

+ 2 - 0
include/SimilaritySearch.hpp

@@ -16,6 +16,8 @@ public:
     // strict: trueならdHashとpHashの両方、falseなら片方が閾値以下であれば類似と判定
     static std::vector<DuplicateGroup> findDuplicates(const std::vector<ImageData>& images, int threshold = 5, bool strict = false);
 
+    static std::vector<ImageData> findSimilarImages(const ImageData& image, const std::vector<ImageData>& images, int threshold = 5, bool strict = false);
+
 private:
     // 内部で使用されるシンプルなクラスタリングアルゴリズム
 };

+ 8 - 46
src/MainWindow.cpp

@@ -330,31 +330,10 @@ void MainWindow::dropEvent(QDropEvent *e) {
       dropped.timestamp = fileInfo.lastModified().toSecsSinceEpoch();
       foundGroup.images.push_back(dropped);
 
-      for (const auto &cand : candidates) {
-        // 自分自身(パスが同じ)は除外
-        if (cand.path == dropped.path)
-          continue;
-
-        bool match = false;
-        if (m_strictMode) {
-          if (ImageHasher::hammingDistance(dhash, cand.dhash) <=
-                  m_currentThreshold &&
-              ImageHasher::hammingDistance(phash, cand.phash) <=
-                  m_currentThreshold) {
-            match = true;
-          }
-        } else {
-          if (ImageHasher::hammingDistance(dhash, cand.dhash) <=
-                  m_currentThreshold ||
-              ImageHasher::hammingDistance(phash, cand.phash) <=
-                  m_currentThreshold) {
-            match = true;
-          }
-        }
-        if (match) {
-          foundGroup.images.push_back(cand);
-        }
-      }
+      auto similar = SimilaritySearch::findSimilarImages(
+          dropped, candidates, m_currentThreshold, m_strictMode);
+      foundGroup.images.insert(foundGroup.images.end(), similar.begin(),
+                               similar.end());
 
       // 重複が見つかった場合のみ追加(自分1枚だけなら追加しない)
       if (foundGroup.images.size() > 1) {
@@ -796,27 +775,10 @@ void MainWindow::onUrlDownloadFinished(QNetworkReply *reply) {
   m_model->addThumbnail(dropped.path,
                         qimg.copy()); // copy to ensure data ownership
 
-  for (const auto &cand : candidates) {
-    bool match = false;
-    if (m_strictMode) {
-      if (ImageHasher::hammingDistance(dhash, cand.dhash) <=
-              m_currentThreshold &&
-          ImageHasher::hammingDistance(phash, cand.phash) <=
-              m_currentThreshold) {
-        match = true;
-      }
-    } else {
-      if (ImageHasher::hammingDistance(dhash, cand.dhash) <=
-              m_currentThreshold ||
-          ImageHasher::hammingDistance(phash, cand.phash) <=
-              m_currentThreshold) {
-        match = true;
-      }
-    }
-    if (match) {
-      foundGroup.images.push_back(cand);
-    }
-  }
+  auto similar = SimilaritySearch::findSimilarImages(
+      dropped, candidates, m_currentThreshold, m_strictMode);
+  foundGroup.images.insert(foundGroup.images.end(), similar.begin(),
+                           similar.end());
 
   std::vector<DuplicateGroup> results;
   if (foundGroup.images.size() > 1) {

+ 17 - 0
src/SimilaritySearch.cpp

@@ -123,3 +123,20 @@ SimilaritySearch::findDuplicates(const std::vector<ImageData> &images,
 
   return results;
 }
+
+
+std::vector<ImageData> SimilaritySearch::findSimilarImages(
+    const ImageData &image, const std::vector<ImageData> &images, int threshold,
+    bool strict) {
+  auto FilterFunc = [&](const ImageData &cand) {
+    if (cand.path == image.path)
+      return false;
+    int distD = ImageHasher::hammingDistance(image.dhash, cand.dhash);
+    int distP = ImageHasher::hammingDistance(image.phash, cand.phash);
+    bool similar = strict ? (distD <= threshold && distP <= threshold)
+                          : (distD <= threshold || distP <= threshold);
+    return similar;
+  };
+
+  return QtConcurrent::blockingFiltered(images, FilterFunc);
+}