Streamlit调用cv2.inRange报src非numpy数组错误排查
错误触发原因
- 直接原因:
cv2.inRange要求输入的源图像必须是NumPy数组/OpenCV UMat格式,但代码中传入的get_img是Streamlit文件上传组件返回的UploadedFile文件对象,不满足OpenCV的入参要求,直接触发参数类型错误。 - 隐含逻辑错误:HSV颜色阈值必须应用在HSV颜色空间的图像上,原代码即使修复类型问题,也缺少将RGB/BGR格式原图转换为HSV空间的步骤,无法得到正确的颜色提取结果。
- 交互逻辑bug:将HSV下限、上限拆分为两个独立表单,点击任意一个提交按钮时,另一组未提交的参数不会同步更新,会导致阈值计算错误。
修复方案
- 调整图像加载逻辑:将上传的文件对象转换为NumPy数组格式的图像数据,供OpenCV调用。
- 补全颜色空间转换步骤:传入
cv2.inRange前,先将RGB格式的原图转换为HSV颜色空间。 - 合并阈值输入表单:将6个HSV通道阈值输入放在同一个表单中,用单个提交按钮触发计算,保证参数同步。
- 给数值输入框添加取值范围限制:OpenCV中HSV的H通道取值范围为0179,S、V通道取值范围为0255,添加范围校验避免非法输入。
修复后的核心功能代码如下:
import cv2 import numpy as np from PIL import Image import streamlit as st def load_img(img_file): img_pil = Image.open(img_file) return np.array(img_pil) def detection(): get_img = st.file_uploader('Upload An Image',type=['png','jpg','jpeg']) select_det = st.sidebar.selectbox('Select Detection Category', ['Color Detection', 'Eye Pupil Detection', 'Edge Detection', 'Car Detection']) if select_det == "Color Detection": if get_img is not None: img_rgb = load_img(get_img) st.image(img_rgb, caption="Original Image") # 单表单收纳所有HSV阈值输入 hsv_form = st.sidebar.form('hsv_threshold_form') lower0 = int(hsv_form.number_input('H Lower', min_value=0, max_value=179, value=0)) lower1 = int(hsv_form.number_input('S Lower', min_value=0, max_value=255, value=0)) lower2 = int(hsv_form.number_input('V Lower', min_value=0, max_value=255, value=0)) upper0 = int(hsv_form.number_input('H Upper', min_value=0, max_value=179, value=179)) upper1 = int(hsv_form.number_input('S Upper', min_value=0, max_value=255, value=255)) upper2 = int(hsv_form.number_input('V Upper', min_value=0, max_value=255, value=255)) submit = hsv_form.form_submit_button('Apply HSV Mask') if submit: # 转HSV空间后再做掩膜计算 img_hsv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV) lower_val = np.array([lower0,lower1,lower2],dtype=np.uint8) upper_val = np.array([upper0,upper1,upper2],dtype=np.uint8) mask = cv2.inRange(img_hsv, lower_val, upper_val) result = cv2.bitwise_and(img_rgb, img_rgb, mask=mask) # 输出结果 st.subheader("HSV Lower Bound") st.write(lower_val) st.subheader("HSV Upper Bound") st.write(upper_val) st.image(mask, caption="Mask") st.image(result, caption="Detection Result")
注:如果用
cv2.imdecode直接读取上传文件得到的是BGR格式图像,颜色空间转换需要替换为cv2.COLOR_BGR2HSV,否则颜色通道顺序错误会导致结果异常。
内容的提问来源于stack exchange,提问作者Pythonic User
相关产品推荐
相关产品推荐

