OpenCV - 如何计算 Mat 的对数?

OpenCV - How to claculate logarithm of a Mat?

我正在尝试根据以下公式计算两个向量 XY

其中:

我决定使用两个 Mat 作为向量:

    Mat X, Y, B, G, R, input_f;

    // read RGB image
    Mat input = imread("an RGB image");

    // convert to float to deal with larger numbers
    input.convertTo(input_f, CV_64FC3);

    // split the image into 3 channels
    vector<Mat> channels(3);
    split(input_f, channels);
    B = channels[0];
    G = channels[1];
    R = channels[2];

    // calculate X , Y vectors
    Mat div_x, div_y;
    divide(R, G, div_x); // R(p_i) / G(p_i)
    divide(B, G, div_y); // B(p_i) / G(p_i)
    div_x.setTo(1, Mat(div_x == 0)); // set zeros to ones to avoid large negative numbers
    div_y.setTo(1, Mat(div_y == 0));
    log(div_x, X); // X = log(R(p_i) / G(p_i))
    log(div_y, Y); // Y = log(B(p_i) / G(p_i))

因此,我在 documentaion:

中将零值更改为一
void log(InputArray src, OutputArray dst);

where C is a large negative number (about -700 in the current implementation).

我不想要大的负数,因为稍后我要将XY的所有像素值相加,总和变为-nan

我确定我取对数的方式有问题,因为结果是错误的。我应该如何以正确的方式做到这一点?


例如,对于这张图片:

XY 值应该是这样的(蓝点):

但就我而言,它们是这样的:

这些是垫子:


根据下面的答案,我将此添加到代码中以避免零除法:

R += 1;
B += 1;
G += 1;

但是现在我的情节看起来还是不一样:

根据下面的回答,修正了(OpenCV对数函数取绝对值的log):

很难说出您到底做错了哪一部分(矩阵除法、将零更改为一,或调用矩阵上的日志)。不管怎样,我只是根据你问题中的方程式实现了你的算法,我得到的结果或多或少是你所期望的(使用你的图像):

代码很简单,只是一步步计算方程:

  cv::Mat bgr[3];
  cv::Mat pic = cv::imread(PATH_TO_FILE);
  cv::split(pic, bgr);
  cv::Mat B = bgr[0];
  cv::Mat G = bgr[1];
  cv::Mat R = bgr[2];
  std::vector<float> X;
  std::vector<float> Y;
  std::transform(R.data, R.data + R.total(), G.data, std::back_inserter(X),
    [](uint8_t r, uint8_t g)
    {
      return std::log((float)r/(float)g);
    });
  std::transform(B.data, B.data + B.total(), G.data, std::back_inserter(Y),
    [](uint8_t b, uint8_t g)
    {
      return std::log((float)b/(float)g);
    });

使用 gnuplot 创建的图形。 X X 轴向量,Y Y 轴向量。 X.size() == Y.size() == 11532.

您可能应该调查 G[i] == 0 情况下应该发生什么,因为您可能会得到 "Floating point exception"。也是分子和分母都为零的特殊情况。

如果你想避免大的负日志,只改变分子的值(比方说从 0 到 1)。不要改变除法结果,因为在大分母的情况下已经有很大的不同了。