You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python检测并移除数据集中包含多张子图的图片?

使用Python检测数据集中的多子图人像图片

针对数据集中包含多张子图拼接的人像图片,你可以通过以下几种实用方法批量检测:

方法一:基于人脸检测统计数量

这类多子图图片通常包含大量人脸,通过统计单张图片中的人脸数量,就能快速筛选出目标图片。推荐使用dlib或OpenCV的人脸检测器,其中dlib的HOG检测器对人像检测精度较高。

实现代码

import dlib
import cv2
import os

# 初始化dlib人脸检测器
detector = dlib.get_frontal_face_detector()

def detect_multi_face_image(image_path, threshold=5):
    img = cv2.imread(image_path)
    if img is None:
        return False
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 检测人脸
    faces = detector(gray, 1)
    # 人脸数量超过阈值则判定为多子图图片
    return len(faces) > threshold

# 遍历数据集目录
dataset_dir = "your_dataset_path"
for filename in os.listdir(dataset_dir):
    if filename.endswith((".jpg", ".png")):
        img_path = os.path.join(dataset_dir, filename)
        if detect_multi_face_image(img_path):
            print(f"检测到多子图图片:{filename}")

注意事项

  • 可根据数据集实际情况调整threshold阈值(子图数量少的话,阈值可设为2或3);
  • 针对模糊或小尺寸子图,可提升检测器的检测级别(detector(gray, 2)),但会增加耗时。

方法二:检测图像中的网格分割线

如果多子图是规则网格排列的(比如行列布局),可以通过边缘检测+霍夫直线变换,识别图像中的水平/垂直线条,判断是否存在明显的分割布局。

实现代码

import cv2
import numpy as np
import os

def detect_grid_layout(image_path, line_threshold=4):
    img = cv2.imread(image_path)
    if img is None:
        return False
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # Canny边缘检测
    edges = cv2.Canny(gray, 50, 150, apertureSize=3)
    # 霍夫直线变换检测直线
    lines = cv2.HoughLines(edges, 1, np.pi/180, 200)
    if lines is None:
        return False
    
    horizontal_lines = 0
    vertical_lines = 0
    # 区分水平和垂直线(角度接近0或90度)
    for rho, theta in lines[:, 0]:
        angle = np.degrees(theta)
        if abs(angle) < 10 or abs(angle - 180) < 10:
            horizontal_lines += 1
        elif abs(angle - 90) < 10:
            vertical_lines += 1
    
    # 水平和垂直线数量均超过阈值则判定为网格布局多子图
    return horizontal_lines >= line_threshold and vertical_lines >= line_threshold

# 遍历数据集
dataset_dir = "your_dataset_path"
for filename in os.listdir(dataset_dir):
    if filename.endswith((".jpg", ".png")):
        img_path = os.path.join(dataset_dir, filename)
        if detect_grid_layout(img_path):
            print(f"检测到网格布局多子图图片:{filename}")

注意事项

  • cv2.HoughLines的阈值参数(200)需要根据图片尺寸调整,避免误检;
  • 仅适用于规则排列的多子图,对不规则拼接的图片效果较差。

方法三:图像块相似度分析

如果多子图属于同一风格(比如都是证件照),可以将图像分割为多个均等块,计算块之间的结构相似度(SSIM),若存在多个高度相似的块,说明是多子图拼接。

实现代码

import cv2
import os
from skimage.metrics import structural_similarity as ssim

def split_image_into_blocks(img, rows=2, cols=2):
    h, w = img.shape[:2]
    block_h = h // rows
    block_w = w // cols
    blocks = []
    for i in range(rows):
        for j in range(cols):
            block = img[i*block_h:(i+1)*block_h, j*block_w:(j+1)*block_w]
            blocks.append(block)
    return blocks

def detect_similar_blocks(image_path, similarity_threshold=0.7, rows=3, cols=3):
    img = cv2.imread(image_path)
    if img is None:
        return False
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blocks = split_image_into_blocks(gray, rows, cols)
    similar_count = 0
    total_pairs = 0
    # 计算所有块之间的相似度
    for i in range(len(blocks)):
        for j in range(i+1, len(blocks)):
            total_pairs += 1
            score, _ = ssim(blocks[i], blocks[j], full=True)
            if score >= similarity_threshold:
                similar_count += 1
    # 相似对占比超过50%则判定为多子图
    return similar_count / total_pairs > 0.5 if total_pairs >0 else False

# 遍历数据集
dataset_dir = "your_dataset_path"
for filename in os.listdir(dataset_dir):
    if filename.endswith((".jpg", ".png")):
        img_path = os.path.join(dataset_dir, filename)
        if detect_similar_blocks(img_path):
            print(f"检测到相似子图拼接的图片:{filename}")

注意事项

  • rows和cols需要根据子图的大致排列数量调整;
  • 不适用于子图风格差异大的拼接图片。

内容的提问来源于stack exchange,提问作者wentao wang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 22:36:29