OpenCV 4.0.3中inRange函数报错:输入图像通道数无效(scn=1)
首先看报错核心:Invalid number of channels in input image: 'VScn::contains(scn)' where 'scn' is 1,这说明在执行cvtColor(plate_gradient, plate_gradient, COLOR_BGR2HSV)时,你的plate_gradient是单通道图像,但COLOR_BGR2HSV转换要求输入必须是3通道的BGR图像,所以触发了错误。
错误原因1:形态学操作使用了空的结构元素
看你的代码里这一行:
morphologyEx(plate_img, plate_gradient, MORPH_GRADIENT, new Mat());
你传入了一个空的Mat作为形态学操作的结构元素,这是不符合OpenCV规范的,会导致未定义行为——这里直接让输出的plate_gradient变成了单通道,而非预期的3通道(因为输入plate_img是彩色3通道图)。
错误原因2:HSV范围设置无效
另外,你定义的HSV阈值有两个问题:
- 数值范围不符合OpenCV 8位图像的规范:OpenCV中8位HSV图像的
H范围是0-179,S和V是0-255,你用了浮点数(比如48.6)会被自动取整,可能和预期不符。 - 阈值顺序错误:
low的H值(151)比high的H值(150)大,这样inRange会得到空结果,因为阈值范围要求low <= high。
解决步骤
1. 修复形态学操作的结构元素
创建一个有效的结构元素,比如3x3的矩形核,替换空的Mat:
// 创建3x3的矩形结构元素 Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3)); // 使用有效的结构元素执行形态学梯度 Imgproc.morphologyEx(plate_img, plate_gradient, Imgproc.MORPH_GRADIENT, kernel);
这样处理后,plate_gradient会保持3通道,后续的cvtColor转换就能正常执行。
2. 修正HSV阈值范围
首先调整阈值的顺序,确保low的每个分量都小于等于high的对应分量;其次根据OpenCV的HSV范围调整数值(把浮点数转为符合0-179/0-255的整数)。比如紫色的典型HSV范围可以设置为:
// 调整后的紫色HSV阈值(8位图像) Scalar low = new Scalar(140, 50, 50); Scalar high = new Scalar(170, 255, 255);
如果你的紫色颜色范围跨越了H的0点(比如偏蓝紫到红紫),可以分两次调用inRange,然后用bitwise_or合并结果:
Mat mask1 = new Mat(); Mat mask2 = new Mat(); Core.inRange(plate_gradient, new Scalar(160, 50, 50), new Scalar(179, 255, 255), mask1); Core.inRange(plate_gradient, new Scalar(0, 50, 50), new Scalar(10, 255, 255), mask2); Core.bitwise_or(mask1, mask2, boosted_plate_gradient);
3. 可选:检查convertTo的对比度增强操作
你的代码里:
plate_gradient.convertTo(plate_gradient, -1, 9.5, -70);
这个操作会把像素值缩放9.5倍再减70,对于8位图像很容易出现溢出(超过255或低于0会被截断),导致图像细节丢失。如果是为了增强对比度,更推荐使用直方图均衡化(针对单通道,比如HSV的V通道):
// 先转HSV,单独增强V通道 Mat hsv = new Mat(); Imgproc.cvtColor(plate_gradient, hsv, Imgproc.COLOR_BGR2HSV); List<Mat> channels = new ArrayList<>(); Core.split(hsv, channels); // 均衡化V通道 Imgproc.equalizeHist(channels.get(2), channels.get(2)); Core.merge(channels, hsv); // 再转回去或者直接用hsv做inRange
内容的提问来源于stack exchange,提问作者Ryan Andrei Perez

