title: Compute absolute values of X and Y derivatives using OpenCV
body: <p>This seems like a pretty straightforward request, but I'm finding the problem a bit subtle. I just want 8-bit unsigned versions of X and Y derivatives. The source image is also 8-bit unsigned.</p>
  
  <p>Here's one approach I've used:</p>
  
  <pre><code>  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);
  </code></pre>
  
  <p>What I don't really like is the use of the <code>normalize</code> function. It seems wasteful. If I try to compute the Sobel operator directly into an 8-bit image (by setting <code>ddepth</code> to <code>-1</code>), it appears to "cut off" all of the negative values. If I try to compute the absolute value and then divide by 8 (to approximately map the absolute value of Sobel operator to [0, 255]), it's still a 16-bit image and I need to convert it to 8-bit, which again seems wasteful. Is there a better way of doing this?</p>
  
  <p>I suppose an important aspect of the question is how to perform operations on 16-bit signed images and somehow have the results placed directly into an 8-bit image. That way, you don't have to run an additional conversion after the fact.</p>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>Here's the final solution:</p>
  
  <pre><code>  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);
  </code></pre>