Python获取图像内矩形框边缘坐标遇下标错误,求解决方案
问题解决与代码修正
错误原因
报错TypeError: 'JpegImageFile' object is not subscriptable是因为最后一行使用了PIL库打开的image对象进行下标切片,但PIL的JpegImageFile并不支持这种numpy数组式的切片操作,必须使用转换后的numpy数组来完成切片。
修正后的代码
方案1:基于现有代码修改
import cv2 import numpy as np from PIL import Image # 打开图像并转换为numpy数组 image= Image.open(r"C:/Users/LikithP/OneDrive - Ennoventure Inc/Documents/Projects/Gold_Bar/finding_corner_points/mask_images/enc-1.jpg") numpy_data = np.array(image) img = numpy_data[:,:,0] # 二值化与形态学处理 _, th = cv2.threshold(img, img.mean(), 255, cv2.THRESH_BINARY_INV) th = cv2.morphologyEx(th, cv2.MORPH_CLOSE, np.ones((3,3))) # 寻找矩形边缘坐标 x1, y1 = 0, 0 y2, x2 = th.shape[:2] while np.all(th[:,x1]==255): x1 += 1 while np.all(th[:,x2-1]==255): x2 -= 1 while np.all(th[y1,:]==255): y1 += 1 while np.all(th[y2-1,:]==255): y2 -= 1 # 使用numpy数组切片,而非PIL对象 cv2.imwrite("cropped_image.jpg", numpy_data[y1:y2, x1:x2]) # 输出最终矩形框坐标 print(f"矩形左上角坐标: ({x1}, {y1})") print(f"矩形右下角坐标: ({x2}, {y2})")
方案2:全程使用cv2读取图像(更简洁)
如果不需要PIL的额外功能,建议直接用cv2读取图像,避免跨库对象混用:
import cv2 import numpy as np # 直接用cv2读取灰度图 img = cv2.imread(r"C:/Users/LikithP/OneDrive - Ennoventure Inc/Documents/Projects/Gold_Bar/finding_corner_points/mask_images/enc-1.jpg", cv2.IMREAD_GRAYSCALE) # 二值化与形态学处理 _, th = cv2.threshold(img, img.mean(), 255, cv2.THRESH_BINARY_INV) th = cv2.morphologyEx(th, cv2.MORPH_CLOSE, np.ones((3,3))) # 寻找矩形边缘坐标 x1, y1 = 0, 0 y2, x2 = th.shape[:2] while np.all(th[:,x1]==255): x1 += 1 while np.all(th[:,x2-1]==255): x2 -= 1 while np.all(th[y1,:]==255): y1 += 1 while np.all(th[y2-1,:]==255): y2 -= 1 # 裁剪并保存图像 cv2.imwrite("cropped_image.jpg", img[y1:y2, x1:x2]) # 输出最终矩形框坐标 print(f"矩形左上角坐标: ({x1}, {y1})") print(f"矩形右下角坐标: ({x2}, {y2})")
额外说明
- 原代码里的
y2-1和x2-1可以去掉,因为numpy切片是左闭右开区间,numpy_data[y1:y2, x1:x2]正好能包含从y1到y2-1、x1到x2-1的所有像素。 - 如果图像存在多个轮廓,逐行逐列扫描的方式仅适用于单一矩形区域;复杂场景下,建议使用
cv2.findContours提取轮廓后获取外接矩形,准确性更高。
内容的提问来源于stack exchange,提问作者Likith P
相关产品推荐
相关产品推荐

