OpenCV Java:保留指定HSV范围像素,其余设灰度却变黑的原因与修正
回答
问题原因
- 掩码逻辑与初始化错误:
Core.inRange生成的mask中,符合HSV条件的像素为白色(255,有效区域),不符合的为黑色(0,无效区域)。你先执行grey.copyTo(result, mask),只会把mask有效区域的灰度像素复制到空的result中,非有效区域保持初始黑色;后续image.copyTo(result, mask)仅覆盖相同有效区域,非有效区域始终未被填充。 - 通道数不匹配:灰度图
grey是单通道,原图像image是三通道,直接混合操作会导致通道兼容问题,进一步加剧显示异常。
修正代码
public class ThresholdHSV { static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } public static void main(String[] args) { Mat image = Imgcodecs.imread("src/playground/input.png"); Mat hsv = new Mat(); // 补充完整类名引用,避免编译错误 Imgproc.cvtColor(image, hsv, Imgproc.COLOR_BGR2HSV); int minHue = 168; int maxHue = 180; int minSaturation = 130; int maxSaturation = 220; int minValue = 120; int maxValue = 220; Mat mask = new Mat(); Core.inRange(hsv, new Scalar(minHue, minSaturation, minValue), new Scalar(maxHue, maxSaturation, maxValue), mask); Mat grey = new Mat(); Imgproc.cvtColor(image, grey, Imgproc.COLOR_BGR2GRAY); // 将单通道灰度图转为三通道BGR格式,与原图像通道数一致 Mat grey3Channel = new Mat(); Imgproc.cvtColor(grey, grey3Channel, Imgproc.COLOR_GRAY2BGR); // 以三通道灰度图作为结果图的初始值,确保非有效区域为灰度 Mat result = grey3Channel.clone(); // 将原图像中符合条件的区域覆盖到结果图上 image.copyTo(result, mask); Imgcodecs.imwrite("src/playground/output.png", result); } }
关键说明
- 通道统一:必须把单通道灰度图转为三通道,否则单通道与三通道图像混合会导致数据异常,显示为黑色或乱码。
- 初始化顺序调整:先将三通道灰度图作为结果图的基础,再用原图像覆盖mask匹配区域,这样非匹配区域自然是灰度,匹配区域保留彩色,完全符合需求。
内容的提问来源于stack exchange,提问作者Starnec
相关产品推荐
相关产品推荐

