自动删除相同的图片,自动处理大量图片

经常会遇到文件夹里有很多重复图片的情况。

这种时候手动去删除会很浪费时间,可以采用以下代码对相同的图片进行自动删除,让每一个图片都被不重不漏地保留下来。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import shutil

import cv2
import numpy as np
import os
import pandas as pd
import traceback

# 均值哈希算法
def aHash(img,shape=(10,10)):
    # 缩放为10*10
    img = cv2.resize(img, shape)
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # s为像素和初值为0,hash_str为hash值初值为''
    s = 0
    hash_str = ''
    # 遍历累加求像素和
    for i in range(shape[0]):
        for j in range(shape[1]):
            s = s + gray[i, j]
    # 求平均灰度
    avg = s / 100
    # 灰度大于平均值为1相反为0生成图片的hash值
    for i in range(shape[0]):
        for j in range(shape[1]):
            if gray[i, j] > avg:
                hash_str = hash_str + '1'
            else:
                hash_str = hash_str + '0'
    return hash_str

# 差值感知算法
def dHash(img,shape=(10,10)):
    # 缩放10*11
    img = cv2.resize(img, (shape[0]+1, shape[1]))
    # 转换灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    hash_str = ''
    # 每行前一个像素大于后一个像素为1,相反为0,生成哈希
    for i in range(shape[0]):
        for j in range(shape[1]):
            if gray[i, j] > gray[i, j + 1]:
                hash_str = hash_str + '1'
            else:
                hash_str = hash_str + '0'
    return hash_str


# 感知哈希算法(pHash)
def pHash(img,shape=(10,10)):
    # 缩放32*32
    img = cv2.resize(img, (32, 32))  # , interpolation=cv2.INTER_CUBIC

    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 将灰度图转为浮点型,再进行dct变换
    dct = cv2.dct(np.float32(gray))
    # opencv实现的掩码操作
    dct_roi = dct[0:10, 0:10]

    hash = []
    avreage = np.mean(dct_roi)
    for i in range(dct_roi.shape[0]):
        for j in range(dct_roi.shape[1]):
            if dct_roi[i, j] > avreage:
                hash.append(1)
            else:
                hash.append(0)
    return hash


# 通过得到RGB每个通道的直方图来计算相似度
def classify_hist_with_split(image1, image2, size=(256, 256)):
    # 将图像resize后,分离为RGB三个通道,再计算每个通道的相似值
    image1 = cv2.resize(image1, size)
    image2 = cv2.resize(image2, size)
    sub_image1 = cv2.split(image1)
    sub_image2 = cv2.split(image2)
    sub_data = 0
    for im1, im2 in zip(sub_image1, sub_image2):
        sub_data += calculate(im1, im2)
    sub_data = sub_data / 3
    return sub_data


# 计算单通道的直方图的相似值
def calculate(image1, image2):
    hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])
    hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])
    # 计算直方图的重合度
    degree = 0
    for i in range(len(hist1)):
        if hist1[i] != hist2[i]:
            degree = degree + (1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))
        else:
            degree = degree + 1
    degree = degree / len(hist1)
    return degree

# Hash值对比
def cmpHash(hash1, hash2,shape=(10,10)):
    n = 0
    # hash长度不同则返回-1代表传参出错
    if len(hash1)!=len(hash2):
        return -1
    # 遍历判断
    for i in range(len(hash1)):
        # 相等则n计数+1,n最终为相似度
        if hash1[i] == hash2[i]:
            n = n + 1
    return n/(shape[0]*shape[1])

def remove_similarity_picture(path,s):
    # 罗列path下所有文件,返回文件名数组
    file = os.listdir(os.path.join(path,s))
    print(file)
    # 遍历文件
    for i, o in enumerate(file):
        # img1 = cv2.imread(os.path.join(path, o))
        # 判断该图像是否还在文件夹中,因为有可能因为重复已经被删除了
        file1 = os.listdir(os.path.join(path,s))
        if o in file1:
            print(1)
            # 若还存在文件夹中就读取该图片文件
            img1=cv2.imdecode(np.fromfile(os.path.join(path, s, o),dtype=np.uint8),-1)
            # print('img1:',n)
            # 遍历当前文件后面的所有文件
            for a, b in enumerate(file[(i + 1):]):
                # img2 = cv2.imread(os.path.join(path, b))
                # 同样的,也要判断一下该文件夹中还有没有这张图片,因为有可能会有两张以上的重复图像,都会被删除
                file2 = os.listdir(os.path.join(path,s))
                if b in file2:
                    # 若还存在就读取后面的这些图像文件
                    img2 =cv2.imdecode(np.fromfile(os.path.join(path, s, b), dtype=np.uint8), -1)
                    # print('img2:',b)
                    # print(img1, img2)
                    print(o,b,"的相似度如下")
                    # hash1 = aHash(img1)
                    # hash2 = aHash(img2)
                    # n = cmpHash(hash1, hash2)
                    # print('均值哈希算法相似度:', n)
                    #
                    # hash1 = dHash(img1)
                    # hash2 = dHash(img2)
                    # n = cmpHash(hash1, hash2)
                    # print('差值哈希算法相似度:', n)
                    #
                    # hash1 = pHash(img1)
                    # hash2 = pHash(img2)
                    # n = cmpHash(hash1, hash2)
                    # print('感知哈希算法相似度:', n)
                    #
                    # n = calculate(img1, img2)
                    # print('单通道的直方图算法相似度:', n)
                    
                    # 计算相似度
                    try:
                        n = classify_hist_with_split(img1, img2)
                        print('三直方图算法相似度:', n)
                    except Exception as err:
                        info = traceback.format_exc()
                        print(info)
                        os.remove(os.path.join(path,s,b))
                        pass
                        
                    
                    # 如果相似度大于0.95,判定为相似
                    if n>=0.95:
                        print('相似')
                        # 把这些相似图像文件删除
                        oldpath=os.path.join(path,s,b)
                        os.remove(oldpath)



def main():
    
    path = 'D:/Project/test'
    dt = pd.read_csv(path+"/LoadPicture.csv",header=0,sep=',')
    # print(dt.columns)
    
    path_list = []
    for i in dt['Parent SKU']:
        if i not in path_list:
            path_list.append(os.path.join(path,i))
    # print(path_list)
    
    for s in path_list:
        remove_similarity_picture(path,s)
    
if __name__=="__main__":
    main()

有时候大量的文件或者图片需要进行删除,批量修改文件名,移动到其他文件夹,检查该图片是否损坏,或者批量做裁剪,下面就是做这些操作的代码脚本


import os
import shutil
import glob
from PIL import Image
import imghdr
import cv2

# 批量删除xml文件
def my_remove(base_path):

    files = os.listdir('D:/Project/CycleGan/path/facades')
    # print(files)
    for file in files:
        path = os.path.join(base_path,file)
        # print(paths)
        if file[-3:] == 'xml':
            print(file)
            os.remove(path)

# 批量修改文件名
def my_filechange():
    files = os.listdir('C:/Users/Yafex/Desktop/cut_file/clean')

    for i,filename in enumerate(files):   #‘D:/Project/CycleGan/path/to/data/B/train/’是文件夹路径,你也可以替换其他=
        newname = str(900000 + i) + '.jpg'  #把jpg替换成png

        print(filename)
        print(newname)
        os.rename('C:/Users/Yafex/Desktop/cut_file/clean/'+filename, 'C:/Users/Yafex/Desktop/cut_file/clean/'+newname)
# my_filechange()

# 批量移动文件
def my_move(srcfn, dstdir):  ##定义移动函数,参数为待移动的文件路径和目标目录
    if not os.path.isfile(srcfn):  ##判断文件是否存在
        print('srcfn error')

    else:
        srcdir, fn = os.path.split(srcfn)  ##分离绝对路径和相对路径,获得文件名

        if not os.path.exists(dstdir):  ##如果目录不存在,创建目录
            os.makedirs(dstdir)

        dstfn = dstdir + fn  ##生成目录下的文件名
        shutil.move(srcfn, dstfn)  ##移动

# 批量移动文件
def move_all():
    fns = glob.glob('C:/Users/Yafex/Desktop/data/trainA/*.jpg')  ##获取当前目录下所有jpg格式的文件

    src_test = [fn for fn in fns if not (int(fn[-12:-6]) % 5)]

    # src_test = [fn for fn in fns if fn[-9] == 'x' and 1 <= int(fn[-8:-4]) <= 120]  ##获取当前目录下的'x0001-x0120',存为一个list,作为test集,
    src_val = [fn for fn in fns if fn[-9] == 'b' and 1 <= int(fn[-8:-4]) <= 120]  ##同理,获取'b0001-b0120'作为val集
    print(src_test)
    for ind in range(len(src_test)):  ##循环移动所有文件

        my_move(src_test[ind], 'C:/Users/Yafex/Desktop/data/valA/')

    # for ind in range(len(src_val)):  ##循环移动所有文件
    #
    #     my_move(src_val[ind], 'D:/Project/CycleGan/path/to/data/A/val/')

move_all()


# 批量检查图片是否损坏
def check_picture():
    base = 'C:/Users/Yafex/Desktop/shuiyin'

    files = os.listdir(base)
    for f in files:
        if f[-3:] != 'txt':
            file = os.path.join(base,f)
            img = imghdr.what(file)
            if img is None:
            # if file == 'D:/Project/CycleGan/datasets/watermark2clean/trainB\\2012_003375.jpg':
                print(file)
                print(img)
            # print(file)
# check_picture()

# 批量裁剪图片
def make_bbox():

    path = "D:/Project/test_cutting" # 图片和检测坐标文件夹
    path3 = "D:/Project/bboxcut" # 裁剪出来的小图要保存的目录
    # w = 1000 # 原始图片resize
    # h = 1000
    img_total = [] # img空列表
    txt_total = [] # txt空列表

    file = os.listdir(path) # 获取所有文件
    for filename in file: # 遍历所有文件
        first,last = os.path.splitext(filename) # 分离文件名与扩展名,如'a.jpg',分离完之后,结果为'a'和'.jpg'
        if last == ".png": # 图片的后缀名如果是jpg
            img_total.append(first) # 就把该文件名存到img_total列表中
        #print(img_total)
        else:
            txt_total.append(first) # 否则就存到txt_total列表中

    for img_ in img_total: # 遍历img的文件名(不含后缀)
        if img_ in txt_total: # 如果该文件名在txt列表中
            print("文件名:",img_)
            filename_img = img_+".png" # 就直接将其加上图片的后缀名,作为图片名
            # print('filename_img:', filename_img)
            path1 = os.path.join(path,filename_img) # 拼接路径和文件名
            img = cv2.imread(path1) # 按路径读取图片
            # img = cv2.resize(img,(w,h),interpolation = cv2.INTER_CUBIC) # resize图像大小,否则roi区域可能会报错
            h,w,c = img.shape
            filename_txt = img_+".txt" # 拿到对应的检测框数据x_center,y_center,width,height
            # print('filename_txt:', filename_txt)
            n = 1 # 设n为1
            with open(os.path.join(path,filename_txt),"r+",encoding="utf-8",errors="ignore") as f: # 打开txt的检测数据文档
                for line in f: # 遍历该文档
                    aa = line.split(" ") # 按空格切分
                    x_center,y_center,width,height = float(aa[2]),float(aa[3]),float(aa[4]),float(aa[5])   # aa[1]左上点的x_center坐标,aa[2]左上点的y_center坐标,aa[3]图片width,aa[4]图片height

                    lefttopx = int(w * (x_center-width/2.0)) # x_center-width/2,这是左上角的x坐标
                    leftdownx = int(w * (x_center+width/2.0))
                    lefttopy = int(h * (y_center-height/2.0)) # 注意,yolo中的y坐标系是朝下的,和常规坐标系相反,所以y_center-height/2是左上角的y坐标
                    leftdowny = int(h * (y_center+height / 2.0))

                    if lefttopy < 3:
                        lefttopy = 3
                    if lefttopx < 3:
                        lefttopx = 3
                    if leftdowny > h - 3:
                        lefttopy = h - 3
                    if leftdownx > w - 3:
                        lefttopx = w - 3

                    roi = img[lefttopy-3:leftdowny+3,lefttopx-3:leftdownx+3] # 按照[左上y:右下y,左上x:右下x]裁剪小图,其中(y1:y2,x1:x2)需要调参,否则裁剪出来的小图可能不太好
                    # print('roi:', roi) # 如果不resize图片统一大小,可能会得到有的roi为[]导致报错
                    filename_last = img_+"_"+str(n)+".jpg" # 裁剪出来的小图文件名,设为图片名+n的结构,格式为jpg
                    path2 = os.path.join(path3,"roi") # 需要在path3路径下创建一个roi文件夹
                    cv2.imwrite(os.path.join(path2,filename_last),roi) # 将该图片写入roi文件夹中
                    n = n+1 # n+1
        else:
            continue

# make_bbox()

def txt_match_jpg():
    jpg_list = os.listdir('C:/Users/Yafex/Desktop/yolov5-master/datasets/watermark/images/train')

    txt_list = os.listdir('C:/Users/Yafex/Desktop/yolov5-master/datasets/watermark/labels/train')

    for j,t in zip(jpg_list,txt_list):

        print(j,t)

# txt_match_jpg()

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Python是一种广泛使用的编程语言,支持图像处理。这种语言非常适合进行批量处理,因为它可以自动化重复任务,提高工作效率,减少错误。 图片裁剪是图像处理中的基本操作,常用于删除不需要的部分或调整图像大小。Python提供了许多库来进行图像处理,最常用的是Pillow。使用Pillow,我们可以很容易地进行图片批量处理。 要进行批量处理,需要先遍历文件夹中的所有图片文件,然后对每个文件进行裁剪。以下是一个简单的示例代码: ``` from PIL import Image import os # 读取文件夹中所有的图片文件 folder_path = 'image_folder' for filename in os.listdir(folder_path): if filename.endswith('.jpg') or filename.endswith('.png'): # 打开并裁剪图片 img_path = os.path.join(folder_path, filename) img = Image.open(img_path) cropped_img = img.crop((100, 100, 300, 300)) # 保存裁剪后的图片 save_path = os.path.join(folder_path, 'cropped_' + filename) cropped_img.save(save_path) ``` 在上面的代码中,我们首先遍历了文件夹中所有以.jpg或.png为后缀名的图片文件。然后,使用`Image.open()`打开每个图片文件,接着使用`crop()`函数裁剪了图片,最后使用`save()`函数保存裁剪后的图片。 裁剪的参数是一个元组,前两个数代表左上角的坐标,后两个数代表右下角的坐标。在这个例子中,裁剪的大小为200×200像素,左上角的坐标为(100, 100),右下角的坐标为(300, 300)。 总之,Python可以很容易地进行图片处理裁剪,使用Pillow库中的函数和遍历文件夹的技巧即可实现。这种方法可以显著加快处理图片的速度,使得我们可以更加专注于更高级的图像处理任务。 ### 回答2: Python是目前比较热门的编程语言之一,其强大的图像处理能力也备受开发者的关注。其中一种常见的处理图片的方法是批处理裁剪,下面就来谈一谈如何通过Python进行批量的图片裁剪。 首先,我们需要安装Python图像处理库Pillow。Pillow是一个开源的图像处理库,可以方便地进行图片操作。安装完此库后,我们接下来就可以开始编写代码了。 通过Python的os库可以遍历指定目录下的所有图片,随后通过Pillow库中的Image.open()打开图片进行裁剪操作。具体裁剪操作通过使用Image.crop()方法实现。Image.crop()方法有四个参数(x1,y1,x2,y2),表示图像从(x1,y1)裁剪到(x2,y2)的部分。对于多张图片的批量操作,我们可以创建一个循环来依次处理每一张图片,将裁剪后的图片保存在指定目录下。 需要注意的是,进行批处理裁剪时,我们需要先确定好图片裁剪的大小和位置,如果所有图片的裁剪参数都不一样,则需要针对每张图片单独设置裁剪参数,不然可能会出现图片错位的问题。 总之,通过Python进行批量的图片裁剪是一个简单而高效的方式,不仅可以省去手动一个一个裁剪的麻烦,而且由于编程的灵活性,我们可以根据不同的需求灵活地进行调整。 ### 回答3: Python是一种高级编程语言,可以方便地完成图片处理任务。图片处理主要是指对大量图片进行自动处理。其中,裁剪图片图片处理的一个基本操作。 Python提供了众多图片处理相关的库,如Pillow等,都有强大的图片处理能力,可以轻松实现图片裁剪功能。要对图片进行裁剪,首先需要确定裁剪区域。可以使用Pillow库提供的Crop方法来实现。 具体实现步骤如下: 1. 导入Pillow库 `from PIL import Image` 2. 打开图片 `img = Image.open('image.jpg')` 3. 定义裁剪区域 `area = (left, upper, right, lower)` 其中,left、upper表示裁剪区域左上角的坐标;right、lower表示裁剪区域右下角的坐标。 4. 裁剪图片 `crop_img = img.crop(area)` 5. 保存裁剪后的图片 `crop_img.save('crop_image.jpg')` 以上就是使用Python进行图片处理裁剪的基本步骤。通过编写脚本,可以方便地对大量图片进行自动处理,提高工作效率,并且保证处理结果的一致性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不会抓鼠鼠的阿猫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值