这似乎是一个非常简单的请求,但我发现问题有点微妙。我只想要 X 和 Y 导数的 8 位无符号版本。源图像也是 8 位无符号的。
这是我使用过的一种方法:
cv::Mat dx, dy;
cv::Sobel(img, dx, CV_16S, 1, 0);
cv::Sobel(img, dy, CV_16S, 0, 1);
dx = cv::abs(dx);
dy = cv::abs(dy);
cv::normalize(dx, dx8u, 0x00, 0xFF, cv::NORM_MINMAX, CV_8U);
cv::normalize(dy, dy8u, 0x00, 0xFF, cv::NORM_MINMAX, CV_8U);
我真正不喜欢的是normalize
函数的使用。好像很浪费。如果我尝试将 Sobel 运算符直接计算为 8 位图像(通过设置ddepth
为-1
),它似乎会“切断”所有负值。如果我尝试计算绝对值然后除以 8(将 Sobel 算子的绝对值近似映射到 [0, 255]),它仍然是 16 位图像,我需要将其转换为 8 位,即再次显得浪费。有没有更好的方法来做到这一点?
我想这个问题的一个重要方面是如何对 16 位签名图像执行操作,并以某种方式将结果直接放入 8 位图像中。这样,您就不必在事后进行额外的转换。
更新:
这是最终的解决方案:
cv::Mat dx, dy;
cv::Sobel(m, dx, CV_16S, 1, 0);
cv::Sobel(m, dy, CV_16S, 0, 1);
cv::convertScaleAbs(dx / 8, dx);
cv::convertScaleAbs(dy / 8, dy);