如何使用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
相关产品推荐
相关产品推荐

