Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <opencv2/opencv.hpp>
- /*
- Note: I split off this piece of code into a separate function in order
- to simplify the reasoning about the code.
- This is probably not ideal for performance, but it's too early to worry about that now.
- Note: Synced the meaning of x and y (and related variables) with changes in filter_mean.
- Note: Added a count variable as a trivial way to keep track of divisor for mean calculation.
- Note: Fixed the missing division in calculation of the mean.
- Note: Changed the mean calculation to use floating point numbers and added
- rounding to nearest integer. This seems like a nicer way to get the mean.
- Note: Added a check to make sure we're only reading valid pixels.
- In other words, avoid reading values outside the bounds of the input image.
- This is needed to handle processing pixels near the edge of the input image.
- Note: You didn't iterate over the whole window. We need delta x/y to range
- from -framing to +framing inclusive.
- Again it's better to iterate rows before columns due to memory layout.
- */
- uint8_t filter_mean_at(cv::Mat const& image, int32_t x, int32_t y, int32_t framing)
- {
- std::cout << "Applying filter at (" << x << "," << y << ")\n";
- int32_t sum{ 0 };
- int32_t count{ 0 };
- for (int32_t dy = -framing; dy <= framing; ++dy) {
- for (int32_t dx = -framing; dx <= framing; ++dx) {
- int32_t const xx = x + dx;
- int32_t const yy = y + dy;
- if ((xx >= 0) && (xx < image.cols) && (yy >= 0) && (yy < image.rows)) {
- std::cout << " * Processing pixel at (" << xx << "," << yy << ")\n";
- sum += image.at<uint8_t>(yy, xx);
- } else {
- std::cout << " * Skipping pixel at (" << xx << "," << yy << ")\n";
- }
- ++count;
- }
- }
- int32_t mean = cvRound(static_cast<double>(sum) / count);
- std::cout << " Result = " << mean << " (as uint8_t = "
- << static_cast<int32_t>(static_cast<uint8_t>(mean)) << ")\n";
- return mean;
- }
- /*
- Note: Since this is only expected to work with positive and odd window sizes
- we should enforce that. Simple assert will do for now.
- Note: We also expect this to work only with 8-bit unsigned images with either
- one (grayscale) or three (BGR, RGB, whatever) channels. Assert added.
- Note: Cloning the input image to result is unnecessary, since we intend
- to overwrite all the values anyway. It might make debugging harder too.
- Explicitly initializing the Mat to zeros is good enough.
- Note: Due to how the pixels are arranged in the buffer, it's bound to be more
- effective to have outer loop iterate over rows. That way you access
- memory locations in sequence. I swapped the two loops.
- Note: You used x to refer to rows and y to refer to columns. That's unexpected.
- I switched them around to the conventional usage.
- */
- cv::Mat filter_mean(cv::Mat image, int window_size)
- {
- assert((window_size > 0) && (window_size % 2 == 1));
- assert((image.type() == CV_8UC1) || (image.type() == CV_8UC3));
- cv::Mat result = cv::Mat::zeros(image.rows, image.cols, image.type());
- int32_t const framing = window_size / 2;
- for (int32_t y = 0; y < image.rows; ++y) {
- for (int32_t x = 0; x < image.cols; ++x) {
- result.at<uint8_t>(y, x) = filter_mean_at(image, x, y, framing);
- }
- }
- return result;
- }
- int main()
- {
- // Just some small simple 4x4 grayscale image to test this on...
- cv::Mat img = (cv::Mat1b(4, 4)
- << 0, 16, 32, 48
- , 64, 64, 64, 64
- , 128, 128, 128, 192
- , 255, 255, 255, 255
- );
- cv::Mat filtered_image = filter_mean(img, 3);
- std::cout << "Result:\n" << filtered_image << '\n';
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement