最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Python開發(fā)圖像數(shù)據(jù)清洗&圖像質量檢查工具

 更新時間:2025年03月13日 08:34:59   作者:AYangSN  
隨著目前采集的數(shù)據(jù)集中的圖像越來越多,出現(xiàn)了數(shù)據(jù)格式十分雜亂、質量不統(tǒng)一等問題,下面小編就來用Python制作一個圖像數(shù)據(jù)清洗&圖像質量檢查工具吧

隨著目前采集的數(shù)據(jù)集中的圖像越來越多,出現(xiàn)了數(shù)據(jù)格式十分雜亂、質量不統(tǒng)一、部分圖像存在損壞等各種問題。

本程序提供各種圖像數(shù)據(jù)清洗和圖像質量檢查功能,防止模型訓練加載數(shù)據(jù)時出現(xiàn)各種異常。

1.使用各種方式讀取圖像,用于檢查圖像是否損壞

2.讀取圖像exit信息,用于防止標注異常

3.記錄圖像信息

① 圖像編碼格式、分辨率、通道數(shù)、文件大小,便于判斷圖像其他屬性

② MD5,PHash16等值,用于判斷是否存在重復

③ 峰值信噪比(PSNR)、結構相似性(SSIM)等,用于判斷圖像質量

完整代碼

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# 功能:圖像數(shù)據(jù)清洗&圖像質量檢查
# 作者:AYangSN
# 時間:2025-03-12
# 版本:1.0


# here is important imports
import csv
import os
import sys
import glob
import shutil
import argparse
import cv2
import hashlib
import imagehash
import numpy as np
from tqdm import tqdm
from PIL import Image, ImageOps, ExifTags
import pandas as pd
from concurrent.futures import ThreadPoolExecutor, as_completed
from skimage.metrics import structural_similarity as ssim
from scipy.stats import entropy


def check_image_with_pil(filepath):
    """使用PIL檢查圖像是否損壞"""
    try:
        img = Image.open(filepath)
        img.verify()  # 驗證圖像完整性
        img = Image.open(filepath)  # 再次打開以確保圖像可以正常加載
        return True, img
    except Exception as e:
        return False, str(e)

def check_image_with_opencv(filepath):
    """使用OpenCV檢查圖像是否損壞"""
    try:
        image = cv2.imread(filepath)
        if image is None or image.size == 0:
            return False, "OpenCV無法加載圖像"
        return True, image
    except Exception as e:
        return False, str(e)

def check_file_header(filepath):
    """通過讀取文件頭信息檢查圖像格式是否正確"""
    valid_headers = {
        'JPEG': b'\xff\xd8\xff',
        'PNG': b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a',
        'GIF87a': b'GIF87a',
        'GIF89a': b'GIF89a',
        'BMP': b'BM'
    }
    with open(filepath, 'rb') as f:
        header = f.read(8)  # 讀取前8個字節(jié)以覆蓋所有格式
        for format, magic in valid_headers.items():
            if header.startswith(magic):
                return True, None
    return False, "未知的文件頭"


def get_exif_orientation(image):
    try:
        exif = image._getexif()
    except AttributeError:
        exif = None
    if exif is None:
        return None
    exif = {
        ExifTags.TAGS[k]: v
        for k, v in exif.items()
        if k in ExifTags.TAGS
    }
    # 獲取圖像方向信息
    orientation = exif.get('Orientation', None)
    return orientation


def exif_update_image_files(image, orientation, image_file, output_dir):
    '''根據(jù)參數(shù)旋轉圖片'''
    if orientation == 2:
        # left-to-right mirror
        image = ImageOps.mirror(image)
    elif orientation == 3:
        # rotate 180
        image = image.transpose(Image.ROTATE_180)
    elif orientation == 4:
        # top-to-bottom mirror
        image = ImageOps.flip(image)
    elif orientation == 5:
        # top-to-left mirror
        image = ImageOps.mirror(image.transpose(Image.ROTATE_270))
    elif orientation == 6:
        # rotate 270
        image = image.transpose(Image.ROTATE_270)
    elif orientation == 7:
        # top-to-right mirror
        image =  ImageOps.mirror(image.transpose(Image.ROTATE_90))
    elif orientation == 8:
        # rotate 90
        image = image.transpose(Image.ROTATE_90)
    else:
        pass
    
    # 生成輸出路徑
    outpath = "{}/{}".format(output_dir, orientation)
    os.makedirs(outpath, exist_ok=True)

    # 使用opencv讀取,去除exif信息
    img = cv2.cvtColor(np.asarray(image), cv2.COLOR_RGB2BGR)

    # 獲取圖像名
    _, imgname = os.path.split(image_file)
    
    # 重新保存圖片
    cv2.imwrite(outpath+'/'+imgname, img)


def compute_md5(filepath):
    """計算文件的MD5值"""
    hash_md5 = hashlib.md5()
    with open(filepath, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()


def compute_phash(imgpath, hash_size=16):
    # 計算圖像的phash值
    img = Image.open(imgpath)
    phash = imagehash.phash(img, hash_size=hash_size, highfreq_factor=4)
    hex_string = str(phash)
    return hex_string


def diff_phash(p1, p2, hash_size = 8):
    # 計算兩個phash值之間的相似度差異
    return (p1 - p2) / hash_size ** 2


def check_blur(image, ref_image=None):
    """綜合評估圖像的模糊質量"""
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Laplacian 方差
    laplacian_var = cv2.Laplacian(gray, cv2.CV_64F).var()

    # 傅里葉變換
    f = np.fft.fft2(gray)
    fshift = np.fft.fftshift(f)
    magnitude_spectrum = 20 * np.log(np.abs(fshift))
    fourier_energy = np.sum(magnitude_spectrum) / (magnitude_spectrum.shape[0] * magnitude_spectrum.shape[1])

    # Tenengrad 方法
    gradient_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
    gradient_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
    gradient_magnitude = np.sqrt(gradient_x**2 + gradient_y**2)
    tenengrad_value = np.mean(gradient_magnitude)

    # 熵
    hist = cv2.calcHist([gray], [0], None, [256], [0, 256])
    hist_norm = hist.ravel() / hist.max()
    entropy_value = entropy(hist_norm, base=2)

    # SSIM(如果有參考圖像)
    ssim_score = None
    if ref_image is not None:
        gray_ref = cv2.cvtColor(ref_image, cv2.COLOR_BGR2GRAY)
        ssim_score, _ = ssim(gray, gray_ref, full=True)

    return laplacian_var, fourier_energy, tenengrad_value, entropy_value, ssim_score


def process_images(filepath, output_dir):
    # 獲取文件擴展名
    file_extension = os.path.splitext(filepath)[1].lower()

    # 檢查圖像是否損壞
    pil_result, img_pil = check_image_with_pil(filepath)
    opencv_result, img_opencv = check_image_with_opencv(filepath)
    header_result, header_error = check_file_header(filepath)

    # 如果圖像沒有損壞,則繼續(xù)處理
    if pil_result and opencv_result and header_result:
        
        # 獲取文件大小  字節(jié)(bytes)
        file_size = os.path.getsize(filepath)
        
        # 獲取分辨率
        width, height = img_pil.size
        
        # 獲取顏色模式
        color_mode = img_pil.mode
        
        # 獲取位深度
        bit_depth = img_pil.bits if hasattr(img_pil, 'bits') else None
        
        # 獲取通道數(shù)
        channels = len(color_mode) if isinstance(color_mode, str) else None
        
        # 獲取壓縮類型
        compression = img_pil.info.get('compression', 'Unknown')
        
        # 獲取EXIF數(shù)據(jù)
        orientation = get_exif_orientation(img_pil)
        
        # 根據(jù)旋轉信息更新圖像
        if not (orientation is None or orientation==1):
            exif_update_image_files(img_pil, orientation, filepath, os.path.join(output_dir,'exif'))

        # 計算MD5校驗碼
        md5_checksum = compute_md5(filepath)

        # 計算phash16校驗碼
        hex_string = compute_phash(filepath, hash_size=16)

        # # 獲取直方圖
        # hist = img_pil.histogram()

        laplacian_var, fourier_energy, tenengrad_value, entropy_value, ssim_score = check_blur(img_opencv)

        log_entry = {
            'filename': filepath,
            'file_extension': file_extension,
            'pil_check': pil_result,
            'opencv_check': opencv_result,
            'header_check': header_result,
            'header_error': header_error,
            'file_size': file_size,
            'resolution': (width, height),
            'color_mode': color_mode,
            'bit_depth': bit_depth,
            'channels': channels,
            'compression': compression,
            'exif_data': orientation,
            'md5_checksum': md5_checksum,
            'phash16_checksum': hex_string,
            'laplacian_var': laplacian_var,
            'fourier_energy': fourier_energy,
            'tenengrad_value': tenengrad_value,
            'entropy_value': entropy_value,
            'ssim_score': ssim_score
        }
    else:
        log_entry = {
            'filename': filepath,
            'file_extension': file_extension,
            'pil_check': pil_result,
            'opencv_check': opencv_result,
            'header_check': header_result,
            'header_error': header_error,

        }
        # 將損壞的文件復制到指定的輸出目錄下
        shutil.copy(filepath, os.path.join(output_dir, 'broken'))

    # 輸出結果
    print(f"文件名: {filepath}")
    print(f"PIL檢查: {'成功' if pil_result else '失敗'}")
    print(f"OpenCV檢查: {'成功' if opencv_result else '失敗'}")
    print(f"文件頭檢查: {'成功' if header_result else '失敗'} - {header_error}")
    print("-" * 40)

    return log_entry


def write_to_csv(log_entries, output_path):
    fieldnames = [
        'filename', 'file_extension', 'pil_check', 'opencv_check', 'header_check', 'header_error', \
        'file_size', 'resolution', 'color_mode', 'bit_depth','channels', 'compression', 'exif_data', 'md5_checksum', 'phash16_checksum', \
        'laplacian_var', 'fourier_energy', 'tenengrad_value', 'entropy_value', 'ssim_score'
    ]
    mode = 'a' if os.path.exists(output_path) else 'w'
    with open(output_path, mode, newline='', encoding='utf-8-sig') as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        if mode == 'w':
            writer.writeheader()
        for entry in log_entries:
            writer.writerow(entry)


def main(input_dir, output_dir):
    os.makedirs(output_dir, exist_ok=True)
    output_csv_path = os.path.join(output_dir, 'image_integrity_report.csv')

    filepaths = []
    # 遍歷輸入目錄下的所有文件,包括子目錄
    for root, dir, fs in tqdm(os.walk(input_dir), desc='Processing Images...'):
        filepaths.extend([os.path.join(root, f) for f in fs if f.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.tiff'))])
    print(f"Found {len(filepaths)} images to process.")

    # 使用線程池進行并行處理
    batch_size = 100  # 每次處理的批大小
    with ThreadPoolExecutor(max_workers=4) as executor:
        futures = {executor.submit(process_images, fp, output_dir): fp for fp in filepaths}
        processed_entries = []
        for future in tqdm(as_completed(futures), desc='Writing CSV...'):
            try:
                log_entry = future.result()
                processed_entries.append(log_entry)
                # print(f"log_entry: {log_entry}")
                # 當達到批次大小時寫入CSV
                if len(processed_entries) >= batch_size:
                    write_to_csv(processed_entries, output_csv_path)
                    processed_entries.clear()
            except Exception as exc:
                print(f'{futures[future]} generated an exception: {exc}')

        # 寫入剩余的數(shù)據(jù)
        if processed_entries:
            write_to_csv(processed_entries, output_csv_path)

    print("報告已生成.")


if __name__ == "__main__":
    # 示例用法
    input_directory = "your_inputpath"
    output_directory = "your_outputpath"
    main(input_directory, output_directory)

到此這篇關于基于Python開發(fā)圖像數(shù)據(jù)清洗&圖像質量檢查工具的文章就介紹到這了,更多相關Python圖像數(shù)據(jù)清洗和質量檢查內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Python爬蟲進階Scrapy框架精文講解

    Python爬蟲進階Scrapy框架精文講解

    這篇文章主要為大家介紹了Python爬蟲進階中Scrapy框架精細講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-10-10
  • Elasticsearch映射字段數(shù)據(jù)類型及管理

    Elasticsearch映射字段數(shù)據(jù)類型及管理

    這篇文章主要介紹了Elasticsearch映射字段數(shù)據(jù)類型及管理的講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-04-04
  • 如何使用Python實現(xiàn)一個簡易的ORM模型

    如何使用Python實現(xiàn)一個簡易的ORM模型

    ORM(Object Relational Mapping)是一種程序設計技術,用于實現(xiàn)面向對象編程語言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉換。本文將介紹如何使用Python實現(xiàn)一個簡易的ORM
    2021-05-05
  • Mac 上切換Python多版本

    Mac 上切換Python多版本

    Mac上自帶了Python2.x的版本,有時需要使用Python3.x版本做開發(fā),但不能刪了Python2.x,可能引起系統(tǒng)不穩(wěn)定,那么就需要安裝多個版本的Python下面通過本文給大家介紹Mac 上切換Python多版本的方法,需要的的朋友一起看看吧
    2017-06-06
  • NumPy 數(shù)組拼接與分割的使用詳解

    NumPy 數(shù)組拼接與分割的使用詳解

    NumPy 提供了多種方法用于??數(shù)組拼接??和??分割,這些操作在數(shù)據(jù)預處理、特征工程和結果整合中至關重要,下面就來詳細的介紹一下NumPy 數(shù)組拼接與分割的使用,感興趣的可以了解一下
    2026-01-01
  • 對Django 中request.get和request.post的區(qū)別詳解

    對Django 中request.get和request.post的區(qū)別詳解

    今天小編就為大家分享一篇對Django 中request.get和request.post的區(qū)別詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • python實現(xiàn)圖片轉換成素描和漫畫格式

    python實現(xiàn)圖片轉換成素描和漫畫格式

    這篇文章主要為大家詳細介紹了python實現(xiàn)圖片轉換成素描和漫畫格式,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • python K近鄰算法的kd樹實現(xiàn)

    python K近鄰算法的kd樹實現(xiàn)

    這篇文章主要介紹了python K近鄰算法的kd樹實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • Windows自動化Python?pyautogui?RPA操作實現(xiàn)

    Windows自動化Python?pyautogui?RPA操作實現(xiàn)

    本文詳細介紹了使用Python的pyautogui庫進行Windows自動化操作的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-01-01
  • Python可視化與交互matplotlib庫的詳細介紹

    Python可視化與交互matplotlib庫的詳細介紹

    matplotlib庫是python中繪制二維,三維圖表的數(shù)據(jù)可視化工具,在2D繪圖領域使用最廣,這篇文章主要介紹了Python可視化與交互matplotlib庫的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-09-09

最新評論

类乌齐县| 巫山县| 枣阳市| 利川市| 金门县| 磐安县| 荥阳市| 志丹县| 肥西县| 内乡县| 海淀区| 萝北县| 克拉玛依市| 黄石市| 广南县| 拜城县| 安平县| 宜州市| 瓮安县| 武鸣县| 淮安市| 射洪县| 汝阳县| 通河县| 普陀区| 晴隆县| 塔城市| 井研县| 龙南县| 克什克腾旗| 邳州市| 孝义市| 博罗县| 西青区| 古蔺县| 安塞县| 桑植县| 松滋市| 鲁山县| 巴塘县| 平山县|