引言
Monica(https://github.com/fengzhizi715/Monica) 是我正在开发的一款跨平台图像编辑器。在 Monica 中,调色功能是最常用的核心模块之一,它支持对图像的色相、饱和度、亮度、高光、阴影、锐化、暗角、色温等多个参数进行灵活调节。
调色本质上是对每个像素的局部调整,虽然逻辑不复杂,但在处理高分辨率图像或进行频繁交互时,对性能的要求极高。
这个模块最初我使用了 OpenCV 的forEach()实现 HSL 空间下的像素遍历,虽然在功能上已基本完整,但随着 Monica 支持更高分辨率的图像输入,操作的流畅度明显下降,性能瓶颈逐渐显现。
为了提升响应速度,我开始对这套逻辑进行重构优化:
尝试使用
ptr()手动遍历像素替换forEach()使用 OpenCV 的
parallel_for_()提升并发性能引入查找表(LUT)优化色彩调整计算
第一阶段:功能实现(forEach + 原始逻辑)
在调色功能的最初实现中,我采用的是的思路:将图像转换为 HSL 空间后,使用 OpenCV 的 forEach 遍历每个像素,对每个通道进行逐一调整。这种方式的优点是代码简洁、逻辑直观、开发效率高,而且对于中小尺寸图片,性能尚可接受。
OpenCV 的Mat::forEach是一个较为现代化的 API,它可以对图像中的每个元素执行 lambda 函数操作,隐藏了繁琐的指针逻辑,并具备一定的自动并行能力(如果启用了 OpenMP/TBB 支持)。对于快速迭代开发来说,这种方式非常友好。
我早期的代码类似这样:
typedef cv::Point3_<uint8_t> Pixel;
......
_cachedHSLImg.forEach<Pixel>([&](Pixel &p, constint * position) -> void {
int i = position[0];
int j = position[1];
auto hslVal = hslCopy.at<cv::Vec3b>(i,j);
int hVal = hslVal[0] + _hueOffset;
while (hVal > 180) {
hVal -= 180;
}
int sval = hslVal[1] + _saturationOffset;
if (sval > 255) {
sval = 255;
}
if (sval < 0) {
sval = 0;
}
unsignedchar highlightFactor = highlightMask.at<unsignedchar>(i, j);
unsignedchar shadowFactor = shadowMask.at<unsignedchar>(i, j);
int lval = _contractScale * hslVal[2] + _lightnessOffset + highlightFactor / 255.0 * _highlightOffset + shadowFactor / 255.0 * _shadowOffset;
if (lval > 255) {
lval = 255;
}
if (lval < 0) {
lval = 0;

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



