如何基于定位的像素裁剪图片以去除白色背景?
解决图片白色背景裁剪问题
你已经通过K-Means完成了背景与目标的分割,接下来只需要计算目标区域的最小外接矩形(Bounding Box),就能精准裁剪掉周围空白。
核心问题修正
你当前获取的「首尾非白色像素」无法代表目标的真实边界——np.where返回的像素是按遍历顺序排列的,首尾像素可能只是目标区域内的某两个点,并非最边缘的边界。正确的做法是提取所有非白色像素的行、列极值,得到目标的上下左右边界。
修改后的完整代码
import cv2 import numpy as np import matplotlib.pyplot as plt # 读取并转换颜色空间 image = cv2.imread('1.jpg') image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # K-Means聚类分割 pixel_values = image_rgb.reshape((-1, 3)).astype(np.float32) criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2) k = 2 _, labels, centers = cv2.kmeans(pixel_values, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) # 生成分割后的图像 centers = np.uint8(centers) segmented_image = centers[labels.flatten()].reshape(image_rgb.shape) # 计算目标区域的边界 # 获取所有非白色像素的坐标(注意:np.where返回的是(行索引, 列索引),对应(y, x)) non_white_coords = np.where((segmented_image != 255).all(axis=2)) min_y, max_y = non_white_coords[0].min(), non_white_coords[0].max() min_x, max_x = non_white_coords[1].min(), non_white_coords[1].max() # 裁剪原图(如果要裁剪分割后的图,替换成segmented_image即可) cropped_image = image_rgb[min_y:max_y+1, min_x:max_x+1] # 显示结果 plt.figure(figsize=(10, 5)) plt.subplot(121), plt.imshow(segmented_image), plt.title('分割后图像') plt.subplot(122), plt.imshow(cropped_image), plt.title('裁剪后图像') plt.show() # 保存裁剪后的图像 cv2.imwrite('cropped_result.jpg', cv2.cvtColor(cropped_image, cv2.COLOR_RGB2BGR))
关键细节说明
- 边界计算:
(segmented_image != 255).all(axis=2)确保筛选的是RGB三个通道都不为255的像素,避免误判单通道非白的情况。 - 切片范围:Python切片是左闭右开,所以
max_y+1和max_x+1能保证包含最边缘的目标像素。 - 灵活选择:可以选择裁剪原图或分割后的图像,根据需求替换
cropped_image的赋值对象。
内容的提问来源于stack exchange,提问作者00zahra000
相关产品推荐
相关产品推荐

