Compare commits

..

2 Commits

Author SHA1 Message Date
c7e074b73f Base feature set done 2019-01-01 23:36:58 +02:00
6649744654 Debug printing 2019-01-01 23:14:34 +02:00
2 changed files with 18 additions and 3 deletions

View File

@ -35,5 +35,7 @@ executable imageduplicates
, recursion-schemes
, text
, transformers
, directory
, filepath
hs-source-dirs: src
default-language: Haskell2010

View File

@ -4,12 +4,16 @@
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
module Main where
import Codec.Picture
import Codec.Picture.Extra (scaleBilinear)
import Control.Exception (SomeException, try)
import Control.Monad (forM_, void, when)
import Data.Bits
import qualified Data.BKTree as BK
import Data.Either (rights)
import Data.List (foldl')
import Data.Word (Word64)
import Options.Generic
@ -17,6 +21,8 @@ import Pipes
import Pipes.Files
import qualified Pipes.Prelude as P
import Pipes.Safe (runSafeT)
import System.Directory (createDirectoryIfMissing, createFileLink)
import System.FilePath (takeFileName, (</>))
data Cmd = Cmd { source :: FilePath
@ -51,6 +57,13 @@ fingerprint = hash . grey . scale . convertRGB8
main :: IO ()
main = do
Cmd{..} <- getRecord "Image duplicate finder"
runSafeT $
runEffect $
for (find source (glob "*.jpg" <> regular) >-> P.mapM (\path -> fmap (path,) <$> liftIO (readImage path)) >-> P.map (fmap (\(path, img) -> Fingerprint path (fingerprint img)))) (liftIO . print)
fingerprints <- rights <$> runSafeT (P.toListM (find source (glob "*.jpg" <> regular) >-> P.mapM (\path -> fmap (path,) <$> liftIO (readImage path)) >-> P.map (fmap (\(path, img) -> Fingerprint path (fingerprint img)))))
let index = foldl' (flip BK.insert) BK.empty fingerprints
forM_ fingerprints $ \fp -> do
let similar = BK.search 1 fp index
when (length similar > 1) $ do
print similar
let targetDir = target </> show (hash fp)
createDirectoryIfMissing True targetDir
forM_ similar $ \fp' -> do
void $ try @SomeException (createFileLink (imagePath fp') (targetDir </> takeFileName (imagePath fp')))