OpenCV修改HSV图像指定像素颜色结果不符的原因排查
颜色偏差核心原因
- OpenCV 8位HSV取值范围和标准HSV范围不匹配,数值溢出是偏色的核心原因
代码里用cv::Vec3b存储像素,本质是8位无符号字符类型,单通道仅能存储0~255的整数。使用cv::cvtColor做COLOR_BGR2HSV转换、输入输出均为8位图时,OpenCV会自动做范围映射:- H(色相)通道:将标准0360°的色相值除以2,压缩到0179区间
- S(饱和度)、V(明度)通道:将标准0100%的数值乘以2.55,拉伸到0255区间
你直接给H通道赋值280,超出8位无符号数的有效逻辑范围,发生整数溢出:280-256=24,H=24刚好对应黄绿色区间,就是你看到的脏绿色。同时S、V赋值100仅对应约39%的饱和度和明度,颜色自然发灰发闷,出不来鲜亮的紫色。
- 代码存在语法bug:mask判断条件里相等判断写错成赋值
条件判断里的(pixelM[1] = 255) && (pixelM[2] = 255)是直接给mask像素的两个通道赋值255,不是判断像素值是否为255,目前修改位置正确只是巧合,换其他mask很容易出现区域误判。 - 你测试H=180时颜色不对也是同因:OpenCV 8位H通道最大值为179(对应标准色相358°),赋值180属于无效值,转换后自然得不到预期的红色。
修正方案
直接替换对应逻辑的代码即可:
cv::cvtColor(frame, frame_hsv, cv::COLOR_BGR2HSV); for (int y = 0; y < mask.size().height; y++) { for (int x = 0; x < mask.size().width; x++) { cv::Vec3b pixelM = mask.at<cv::Vec3b>(cv::Point(x, y)); // 赋值符=改为相等判断符== if ((pixelM[0] == 255) && (pixelM[1] == 255) && (pixelM[2] == 255)) { cv::Vec3b& pixelF = frame_hsv.at<cv::Vec3b>(cv::Point(x, y)); // 标准HSV(280°,100%,100%) 对应OpenCV 8位HSV值为(140, 255, 255) pixelF[0] = 140; pixelF[1] = 255; pixelF[2] = 255; } } } cv::cvtColor(frame_hsv, frame, cv::COLOR_HSV2BGR);
相关效果参考:

内容的提问来源于stack exchange,提问作者opennime
相关产品推荐
相关产品推荐

