0

I am learning image processing with OpenCV in C++. To implement a basic down-sampling algorithm I need to work on the pixel level -to remove rows and columns. However, when I assign values with mat.at<>(i,j) other values are assign - things like 1e-38.

Here is the code :

Mat src, dst;
src = imread("diw3.jpg", CV_32F);//src is a 479x359 grayscale image

//dst will contain src low-pass-filtered I checked by displaying it works fine
Mat kernel;
kernel = Mat::ones(3, 3, CV_32F) / (float)(9);
filter2D(src, dst, -1, kernel, Point(-1, -1), 0, BORDER_DEFAULT);

// Now I try to remove half the rows/columns result is stored in downsampled
    Mat downsampled = Mat::zeros(240, 180, CV_32F);
for (int i =0; i<downsampled.rows; i ++){
    for (int j=0; j<downsampled.cols; j ++){
        downsampled.at<uchar>(i,j) = dst.at<uchar>(2*i,2*j);
    }
}

Since I read here OpenCV outputing odd pixel values that for cout I needed to cast, I wrote downsampled.at<uchar>(i,j) = (int) before dst.at<uchar> but it does not work also.

joachim
  • 11
  • 5
  • First of all, passing `CV_32F` as a second argument of `imread` doesn't make any sense. Next, you make `downsampled` a CV_32F, yet for some reason you access the elements as `uchar`. That means you overwrite one quarter of the bits of a 32bit floating point number with something else.... garbage is the expected result of doing so. – Dan Mašek Jun 21 '20 at 12:23
  • After your comment, I have changed downsample to CV_U8, the values are in (0, 255) now. However when I try to copy the image only the top left quarter of dst is present in downsampled – joachim Jun 21 '20 at 14:21

1 Answers1

0

The second argument to cv::imread is cv::ImreadModes, so the line:

src = imread("diw3.jpg", CV_32F);

is not correct; it should probably be:

cv::Mat src_8u = imread("diw3.jpg", cv::IMREAD_GRAYSCALE);
src_8u.convertTo(src, CV_32FC1);

which will read the image as 8-bit grayscale image, and will convert it to floating point values.

The loop should look something like this:

Mat downsampled = Mat::zeros(240, 180, CV_32FC1);
for (int i = 0; i < downsampled.rows; i++) {
  for (int j = 0; j < downsampled.cols; j++) {
    downsampled.at<float>(i,j) = dst.at<float>(2*i,2*j);
  }
}

note that the argument to cv::Mat::zeros is CV_32FC1 (1 channel, with 32-bit floating values), so Mat::at<float> method should be used.

vasiliykarasev
  • 851
  • 4
  • 10