删除文件夹内的重复图片

使用背景:

        加入你有一堆的图片,有一天你想整理一下,想删除重复或者相似度较高的图,自己手动又太累太耗时...

主类:

import com.sun.jna.platform.FileUtils;
import tool.PublicWays;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

public class DeleteDuplicateImg {

    private static File txtFile;
    private static String foreachFolder;

    public DeleteDuplicateImg(File file, String downloadUrl) {

        if (file != null)
            txtFile = file;
        else {
            txtFile = new File("DownloadImageLog.txt");//为空或仅执行当前类时指定创建txt文件
            PublicWays.creatFile(txtFile);
        }

        if (downloadUrl != null)
            foreachFolder = downloadUrl;
        else {
            System.out.println("请选择需要操作的文件夹");
            foreachFolder = PublicWays.selectSavePath(txtFile);//当为空或仅执行当前类时拉起选择需要遍历的文件夹
        }

        init();
    }

    private static void init() {

        /*创建日志文本文件*/
        String txtName = "Log.txt";
        String savePath = "";
        txtFile = new File(savePath + txtName);
        PublicWays.creatFile(txtFile);
        PublicWays.modifyFileContents(txtFile, "\n" + PublicWays.getCurrentTime("yyyy-MM-dd HH:mm:ss") + "\n\n", false);

        FileUtils fileUtils = FileUtils.getInstance();

        File file = new File(foreachFolder);
        File[] files = file.listFiles();
        assert files != null;
        System.out.println("文件夹内文件数量:" + files.length);

        long startTime, endTime;
        startTime = System.currentTimeMillis();

        ArrayList<int[]> filesList = new ArrayList<>();
        for (File f : files) {
            filesList.add(getData(f));
        }
        ArrayList<File> duplicateFileList = new ArrayList<>();

        endTime = System.currentTimeMillis();
        System.out.println("转化二进制添加至数组耗时: " + (endTime - startTime) + "ms");

        compare(filesList, files, duplicateFileList);//开始遍历

        delete(duplicateFileList, fileUtils);//开始删除重复文件

        endTime = System.currentTimeMillis();
        System.out.println("总耗时: " + (endTime - startTime) + "ms");

    }

    static BufferedImage img, slt;

    /**
     * 将图片转成二进制
     *
     * @param file 需要转存的图片
     * @return 返回二进制数组
     */
    public static int[] getData(File file) {
        try {
            img = ImageIO.read(file);
            slt = new BufferedImage(100, 100,
                    BufferedImage.TYPE_INT_RGB);
            slt.getGraphics().drawImage(img, 0, 0, 100, 100, null);
            int[] data = new int[256];
            int r, g, b, rgb, x, y;//避免重复定义,循环前先全部定义完
            Color myColor;
            for (x = 0; x < slt.getWidth(); x++) {
                for (y = 0; y < slt.getHeight(); y++) {
                    rgb = slt.getRGB(x, y);
                    myColor = new Color(rgb);
                    r = myColor.getRed();
                    g = myColor.getGreen();
                    b = myColor.getBlue();
                    data[(r + g + b) / 3]++;
                }
            }
            return data;
        } catch (Exception exception) {
            System.out.println("出错啦!");
            return null;
        }
    }

    /**
     * 对比两张图片的相似度
     *
     * @param s 第一张图
     * @param t 第二张图
     * @return 返回相似度
     */
    public static float compare(int[] s, int[] t) {
        try {
            float result = 2F;
            int i, abs, max;
            assert s != null;
            assert t != null;
            for (i = 0; i < 256; i++) {
                abs = Math.abs(s[i] - t[i]);
                max = Math.max(s[i], t[i]);
                result += (1 - ((float) abs / (max == 0 ? 1 : max)));
            }

            return (result / 256) * 100;
        } catch (Exception exception) {
            return 0;
        }
    }

    /**
     * 遍历数组,开始对比相似度
     *
     * @param filesList      需要对比相似度文件夹对应转存的二进制数组
     * @param files          需要对比相似度文件夹
     * @param duplicateFiles 用于存储重复的图片数组
     */
    private static void compare(ArrayList<int[]> filesList, File[] files, ArrayList<File> duplicateFiles) {
        long startTime, endTime;
        startTime = System.currentTimeMillis();
        float percent;
        int num = 0, i, j;
        for (i = 4; i < filesList.size(); i++) {
            if (files[i].exists()) {
                for (j = i + 1; j < filesList.size(); j++) {
                    percent = compare(filesList.get(i), filesList.get(j));
                    if (percent >= 90 && files[j].exists()) {
                        duplicateFiles.add(files[j]);
                    }
                    num++;
                }
            } else
                System.out.println(files[i] + " is not exit!");
        }
        endTime = System.currentTimeMillis();
        System.out.println("对比图片耗时: " + (endTime - startTime) + "ms");
        PublicWays.modifyFileContents(txtFile, "对比图片" + num + "次, 共耗时: " + (endTime - startTime) + "ms" + "\n", true);
    }

    /**
     * 删除重复图片
     *
     * @param duplicateFileList 需要删除的重复图片数组
     * @param fileUtils         为避免误操作,用于将图片扔至回收站
     */
    private static void delete(ArrayList<File> duplicateFileList, FileUtils fileUtils) {
        long startTime, endTime;
        startTime = System.currentTimeMillis();
        try {
            for (File f : duplicateFileList) {
                if (f.exists()) {
                    fileUtils.moveToTrash(new File[]{f});
                    PublicWays.modifyFileContents(txtFile, " 删除图片 " + f.getName(), true);
                }
            }
        } catch (IOException ignored) {
        }
        endTime = System.currentTimeMillis();
        System.out.println("删除图片耗时: " + (endTime - startTime) + "ms");
        PublicWays.modifyFileContents(txtFile, "删除" + duplicateFileList.size() + "张图片, 共耗时: " + (endTime - startTime) + "ms" + "\n", true);
    }

    public static void main(String[] args) {
        new DeleteDuplicateImg(null, null);
    }

}

PublicWays类:

     /**
     * 修改指定文件的内容
     * --分割线--
     * FileWriter第二个参数true意为续写,false或不写则为覆盖
     *
     * @param file     需要修改内容的文件
     * @param info     修改的内容
     * @param isAppend 选择是覆写还是续写,true为续写,false为覆写
     */
    public static void modifyFileContents(File file, String info, Boolean isAppend) {
        try {
            FileWriter fileWriter = new FileWriter(file, isAppend);
            fileWriter.write(info);
            fileWriter.flush();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("写入指定" + file.getName().substring(file.getName().lastIndexOf(".") + 1) + "文件内容出错:" + e.getMessage());
        }
    }


    /**
     * 获取当前时间并自定义格式化
     *
     * @param format 自定义格式化格式(yyyy:年 MM:月 dd:日 HH:时 mm:分 ss:秒)
     */
    public static String getCurrentTime(String format) {
        return new SimpleDateFormat(format).format(new Date());
    }

    /**
     * 在指定路径创建指定文件
     *
     * @param file 需要创建的txt文件
     */
    public static void creatFile(File file) {
        if (!file.exists()) {
            try {
                file.createNewFile();
                System.out.println("创建指定" + file.getName().substring(file.getName().lastIndexOf(".") + 1) + "文本文件成功!");
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("创建指定" + file.getName().substring(file.getName().lastIndexOf(".") + 1) + "文本文件出错:" + e.getMessage());
            }
        } else {
            System.out.println("指定" + file.getName().substring(file.getName().lastIndexOf(".") + 1) + "文本文件已存在!");
        }
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
首先,我们需要编写一个函数来计算一张图片的平均像素值。可以使用Python中的PIL库来读取图片并计算平均像素。下面是一个示例函数: ```python from PIL import Image def get_average_pixel(image): """ 计算图片的平均像素值 """ # 打开图片并转换为RGB格式 with Image.open(image).convert('RGB') as img: # 获取所有像素并计算平均值 pixels = img.load() width, height = img.size total_r, total_g, total_b = 0, 0, 0 for x in range(width): for y in range(height): r, g, b = pixels[x, y] total_r += r total_g += g total_b += b num_pixels = width * height avg_r = total_r // num_pixels avg_g = total_g // num_pixels avg_b = total_b // num_pixels return (avg_r, avg_g, avg_b) ``` 接下来,我们可以使用os模块来遍历文件夹中的所有jpg图片,并将它们的平均像素值存储到一个字典中。字典的键是文件名,值是平均像素值。如果有重复的平均像素值,我们只需要保留一个文件即可。最后,我们可以使用sorted函数来按照平均像素值对文件进行排序,并将重复的文件删除。 ```python import os def sort_images_by_average_pixel(folder): """ 按照平均像素值对文件夹中的jpg图片进行排序,并删除重复的文件 """ # 遍历文件夹中的所有jpg图片,并计算平均像素值 images = {} for file in os.listdir(folder): if file.endswith('.jpg'): image_path = os.path.join(folder, file) avg_pixel = get_average_pixel(image_path) images[file] = avg_pixel # 按照平均像素值对图片进行排序 sorted_images = sorted(images.items(), key=lambda x: x[1]) # 删除重复图片 prev_avg_pixel = None for file, avg_pixel in sorted_images: if avg_pixel == prev_avg_pixel: os.remove(os.path.join(folder, file)) else: prev_avg_pixel = avg_pixel ``` 现在,我们可以调用sort_images_by_average_pixel函数来对指定文件夹中的jpg图片进行排序和删除重复文件: ```python folder = '/path/to/folder' sort_images_by_average_pixel(folder) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡#

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值