当前位置: 首页 > news >正文

2025-07-15通过边缘线检测图像里的主体有没有出血

本节观点:一个好的提问就已经解决了问题的90%。

对于问题的描述正确与否决定了解决问题的方法和路径,所以我们在AI时代必须要学会正确的描述问题和表达问题,否则即使有AI辅助也是很难精准的解决问题。

我的问题:

如何利用代码从图片集中筛选出出血的图片,定义出血:提取图片中的边缘,我希望通过设置一个值来界定,比如所有边缘线与图像边缘接触的总条数超过10条才算出血图片,另外图像中的边缘线段至少长20像素才计入有效边缘线段,同时要考虑图片路径含有中文的问题。

如下图所示,其中1,2是出血的图,3,4是没有出血的图。通过上方的描述提交给AI,AI就能帮我们实现批量筛选所有出血的图片。
在这里插入图片描述

特别说明:

国产AI水平确实远低于国外的,同样的问题,GPT一次就搞定了代码,而豆包,qwen,deepseek等从多国产AI提问了N轮最后连最基本的读图时中文路径问题都无法搞定,可笑至极。加油国产AI。

import cv2
import numpy as np
import os
import shutildef read_image_chinese_path(image_path):# 支持中文路径读取image_data = np.fromfile(image_path, dtype=np.uint8)img = cv2.imdecode(image_data, cv2.IMREAD_COLOR)return imgdef is_bleeding_image(image_path, edge_touch_threshold=10, min_edge_length=20):img = read_image_chinese_path(image_path)if img is None:print(f"无法读取图片: {image_path}")return Falseheight, width = img.shape[:2]# 灰度 + Canny 边缘检测gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)edges = cv2.Canny(gray, 100, 200)# 查找轮廓contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)edge_touch_count = 0for cnt in contours:# 计算轮廓长度length = cv2.arcLength(cnt, closed=False)if length < min_edge_length:continue  # 过滤掉短轮廓# 检查是否有点在图像边界for point in cnt:x, y = point[0]if x <= 0 or y <= 0 or x >= width-1 or y >= height-1:edge_touch_count += 1break  # 这条轮廓计数一次就够return edge_touch_count >= edge_touch_thresholddef find_and_move_bleeding_images(folder_path, output_folder, edge_touch_threshold=10, min_edge_length=20):if not os.path.exists(output_folder):os.makedirs(output_folder)for root, _, files in os.walk(folder_path):for file in files:if file.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp')):file_path = os.path.join(root, file)if is_bleeding_image(file_path, edge_touch_threshold, min_edge_length):print(f"检测到出血: {file_path}")# 生成输出路径output_path = os.path.join(output_folder, file)# 如果重名文件,改名避免覆盖base, ext = os.path.splitext(output_path)counter = 1while os.path.exists(output_path):output_path = f"{base}_{counter}{ext}"counter += 1# 移动文件shutil.move(file_path, output_path)if __name__ == "__main__":input_folder = r"images"         # 输入图片文件夹路径output_folder = r"output_images"    # 检测到出血后保存到这里find_and_move_bleeding_images(input_folder, output_folder,edge_touch_threshold=10,min_edge_length=20)print("✅ 所有出血图片已移动至 output_images 文件夹")

最后描述问题过程:
第1次:
我有几张图片,其中有一张图片内容是非常完整的,主体在图的中间(这里要考虑图片的背景,有的图片背景是纯白色,有的图片是纯黑色,有的图片的是其它纯色的背景),而其余的图片都是主体出血。如何利用代码检测或筛选出主体没𠕇出血的图片
出来的代码只能做到60%选对。

第2次:
重新整理一下思路:1,分别取出图像外边1像素宽的边缘,2.分别计算每边的像素色值是否一样,如果计算出有明显不同的像素色值部分的像素总计超过5%单边所有像素色值比例的说明是出血图像。
出来的代码只能做到65%选对。

第3次:
如何利用代码从图片集中筛选出出血的图片,定义出血:提取图片中的边缘,我希望通过设置一个值来界定,比如所有边缘线与图像边缘接触的总条数超过10条才算出血图片,另外图像中的边缘线段至少长20像素才计入有效边缘线段,同时要考虑图片路径含有中文的问题。
出来的代码只能做到95%选对。

最终代码

import cv2
import numpy as np
import os
import shutildef read_image_chinese_path(image_path):"""支持中文路径读取"""image_data = np.fromfile(image_path, dtype=np.uint8)img = cv2.imdecode(image_data, cv2.IMREAD_COLOR)return imgdef has_large_colored_block_with_edges(img, block_size=10, edge_proximity=5):"""检查是否存在大于 block_size 的色块且色块两侧有边缘线,并且色块接近图像边缘"""height, width = img.shape[:2]# 边缘检测gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)edges = cv2.Canny(gray, 100, 200)# 查找轮廓contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)for cnt in contours:x, y, w, h = cv2.boundingRect(cnt)# 判断色块尺寸是否足够大if w >= block_size and h >= block_size:# 检查色块是否靠近图像边缘if (x <= edge_proximity or y <= edge_proximity orx + w >= width - edge_proximity ory + h >= height - edge_proximity):# 检查 ROI 内边缘线roi_edges = edges[y:y+h, x:x+w]top_edge = np.sum(roi_edges[0, :] > 0)bottom_edge = np.sum(roi_edges[-1, :] > 0)left_edge = np.sum(roi_edges[:, 0] > 0)right_edge = np.sum(roi_edges[:, -1] > 0)edge_threshold = 3  # 至少3个像素视作边缘线if (left_edge >= edge_threshold and right_edge >= edge_threshold):return True  # 找到了符合要求的色块return Falsedef is_bleeding_image(image_path, edge_touch_threshold=10, min_edge_length=20, block_size=10):img = read_image_chinese_path(image_path)if img is None:print(f"无法读取图片: {image_path}")return Falseheight, width = img.shape[:2]# 灰度 + 边缘检测gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)edges = cv2.Canny(gray, 100, 200)# 查找所有外轮廓contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)edge_touch_count = 0for cnt in contours:# 计算轮廓长度length = cv2.arcLength(cnt, closed=False)if length < min_edge_length:continue# 检查是否触碰图像边界for point in cnt:x, y = point[0]if x <= 0 or y <= 0 or x >= width-1 or y >= height-1:edge_touch_count += 1break# 条件1:足够多的触边线条if edge_touch_count < edge_touch_threshold:return False# 条件2:是否有色块两侧有边缘if not has_large_colored_block_with_edges(img, block_size):return Falsereturn True  # 两个条件都满足def find_and_move_bleeding_images(folder_path, output_folder, edge_touch_threshold=10, min_edge_length=20, block_size=10):if not os.path.exists(output_folder):os.makedirs(output_folder)for root, _, files in os.walk(folder_path):for file in files:if file.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp')):file_path = os.path.join(root, file)if is_bleeding_image(file_path, edge_touch_threshold, min_edge_length, block_size):print(f"检测到出血: {file_path}")# 生成输出路径output_path = os.path.join(output_folder, file)base, ext = os.path.splitext(output_path)counter = 1while os.path.exists(output_path):output_path = f"{base}_{counter}{ext}"counter += 1# 移动文件shutil.move(file_path, output_path)if __name__ == "__main__":input_folder = r"images"         # 输入文件夹路径output_folder = r"output_images"    # 出血图片保存路径find_and_move_bleeding_images(input_folder, output_folder,edge_touch_threshold=1,    # 触边线条数阈值min_edge_length=2,         # 有效边缘线长度block_size=2               # 色块尺寸阈值)print("✅ 所有出血图片已移动至 output_images 文件夹")

在这里插入图片描述
在这里插入图片描述

http://www.lryc.cn/news/588921.html

相关文章:

  • 【Docker基础】Dockerfile构建与运行流程完全指南:从原理到实践优化
  • Spring MVC2
  • 操作系统——进程
  • 前端-CSS-day4
  • CSS 高阶使用指南
  • Python 函数:从“是什么”到“怎么用”的完整指南
  • QT 中各种坑
  • 【Qt】QWidget核心属性
  • Django基础(二)———URL与映射
  • WSI中sdpc格式文件学习
  • 函数柯里化详解
  • 知识增强型Agent开发新范式:基于ERNIE-4.5的检索增强生成架构实践
  • ubuntu22.04 软创建 RAID1 与配置流程
  • Ubuntu 安装
  • Ubuntu环境下的K3S集群搭建
  • 一文读懂语义解析技术:从规则到神经网络的演进与挑战
  • DGNNet:基于双图神经网络的少样本故障诊断学习模型
  • 暑期算法训练.1
  • Linux下调试器gdb/cgdb的使用
  • 只解析了CHAME记录,如何申请免费的SSL证书
  • Linux 命令:passwd
  • WPF中ListView控件详解
  • 牛客:HJ23 删除字符串中出现次数最少的字符[华为机考][字符串]
  • Linux部署Python服务
  • langchain教程10:LCEL
  • 阿里云 Kubernetes 的 kubectl 配置
  • 深入理解设计模式之外观模式:简化复杂系统的艺术
  • 企业培训视频如何做内容加密防下载防盗录(功能点整理)
  • 优雅的Java:01.数据更新如何更优雅
  • 2025开放原子开源生态大会 | openKylin的技术跃迁和全球协作