Python实现:裁剪图像最亮区域并获取颜色值范围
问题描述
我有一个能检测并圈出图像最亮区域的程序,现在需要获取圈选区域内的颜色值范围。计划是先裁剪该区域,再提取其中所有像素的颜色值,但不知道怎么根据检测到的最亮点位置来裁剪图像。
当前可用代码
import cv2 import numpy as np img1 = cv2.imread('opencv_frame_0.png') img2 = cv2.imread('opencv_frame_1.png') vis = np.concatenate((img1, img2), axis=1) cv2.imwrite('combined.png', vis) # 加载图像并转为灰度图 #image = cv2.imread(args["image"]) image = cv2.imread('combined.png') orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 查找图像中亮度最高区域的坐标 (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(gray) # 显示初步检测结果 cv2.imshow("Naive", image) # 对图像做高斯模糊后再查找最亮区域 #gray = cv2.GaussianBlur(gray, (args["radius"], args["radius"]), 0) gray = cv2.GaussianBlur(gray, (41, 41), 0) (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(gray) image = orig.copy() #cv2.circle(image, maxLoc, args["radius"], (255, 0, 255), 2) cv2.circle(image, maxLoc, 41, (255, 0, 255), 2) # 显示优化后的检测结果 cv2.imshow("Robust", image) cv2.waitKey(0)
失败的裁剪尝试代码
import numpy as np import cv2 # 加载图像并转为灰度图 image = cv2.imread('combined.png') image1 = cv2.imread('combined.png', 0) orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 查找图像中亮度最高区域的坐标 (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(gray) # 显示初步检测结果 #cv2.imshow("Naive", image) # 对图像做高斯模糊后再查找最亮区域 gray = cv2.GaussianBlur(gray, (41, 41), 0) (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(gray) image = orig.copy() cv2.circle(image, maxLoc, 41, (255, 0, 255), 2) # 尝试裁剪圆形区域 height,width = image1.shape mask = np.zeros((height,width), np.uint8) circle_img = cv2.circle(mask,(maxLoc,(255,255,255)) masked_data = cv2.bitwise_and(image, image, mask=circle_img) _,thresh = cv2.threshold(mask,1,255,cv2.THRESH_BINARY) contours = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) x,y,w,h = cv2.boundingRect(contours[0]) crop = masked_data[y:y+h,x:x+w] cv2.waitKey(0)
解决方案
你失败的代码主要是cv2.circle调用语法错误,且未正确处理mask和轮廓提取逻辑。以下是两种可行的实现方式:
方法1:直接提取圆形区域内的像素(推荐)
无需裁剪外接矩形,直接通过mask过滤出圆形内的像素,计算颜色范围:
import cv2 import numpy as np # 加载图像 image = cv2.imread('combined.png') orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 高斯模糊后定位最亮区域 gray = cv2.GaussianBlur(gray, (41, 41), 0) (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(gray) radius = 41 # 创建填充圆形的mask height, width = gray.shape mask = np.zeros((height, width), np.uint8) cv2.circle(mask, maxLoc, radius, 255, -1) # -1表示填充圆形 # 提取圆形区域内的所有像素 mask_bool = mask.astype(bool) pixels = image[mask_bool] # 计算每个颜色通道的范围 b_min, g_min, r_min = pixels.min(axis=0) b_max, g_max, r_max = pixels.max(axis=0) print(f"B通道范围: {b_min} ~ {b_max}") print(f"G通道范围: {g_min} ~ {g_max}") print(f"R通道范围: {r_min} ~ {r_max}") # 可选:可视化裁剪后的圆形区域 x, y = maxLoc x1 = max(0, x - radius) y1 = max(0, y - radius) x2 = min(width, x + radius) y2 = min(height, y + radius) cropped_img = image[y1:y2, x1:x2] cropped_mask = mask[y1:y2, x1:x2] cropped_masked = cv2.bitwise_and(cropped_img, cropped_img, mask=cropped_mask) cv2.imshow("Cropped Bright Area", cropped_masked) cv2.waitKey(0) cv2.destroyAllWindows()
方法2:修复你原有的裁剪逻辑
修正语法错误并适配OpenCV版本差异:
import numpy as np import cv2 image = cv2.imread('combined.png') image1 = cv2.imread('combined.png', 0) orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray, (41, 41), 0) (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(gray) radius = 41 cv2.circle(image, maxLoc, radius, (255, 0, 255), 2) # 修复mask创建逻辑 height,width = image1.shape mask = np.zeros((height,width), np.uint8) cv2.circle(mask, maxLoc, radius, 255, -1) # 修正参数并填充圆形 masked_data = cv2.bitwise_and(image, image, mask=mask) _,thresh = cv2.threshold(mask,1,255,cv2.THRESH_BINARY) # 适配OpenCV4+的findContours返回值 contours, hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) x,y,w,h = cv2.boundingRect(contours[0]) crop = masked_data[y:y+h,x:x+w] cv2.imshow("Cropped", crop) cv2.waitKey(0)
内容的提问来源于stack exchange,提问作者Philip Gerou
相关产品推荐
相关产品推荐

