[Image processing OpenCV (C++ version)] – 5.4 Image smoothing median smoothing (filtering)

Preface:

Welcome to this blog

This column mainly combines OpenCV and C++ to implement some basic image processing algorithms and explain the meaning of each parameter in detail , suitable for daily study, work quick query, etc., updated at any time.

Specific eating method: You can click on this column [OpenCV quick search (updating)] –> search for the operator name or related knowledge points you want to query , or through this blog Easy to understand OpenCV (C ++ version) detailed tutorial – OpenCV function quick search (continuously updated)] Check out the knowledge you want to know, and you can eat it.

Support: If you think the blogger’s article is not bad or you can use it, you can quietly follow the blogger. all right! This is what gives me the greatest support!

Article directory

    • learning target
    • 1. The principle of median smoothing
      • 1.1 Related concepts
      • 1.2 Principle
      • 1.3 Function
    • Two, C++ implementation
      • 2.1 Function introduction
      • 2.2 Specific implementation
    • 3. Summary

Learning Objectives

  • Learn about median smoothing
  • Familiar with the median principle
  • C++ in progress Value smoothing case

Each image may contain some degree of noise. Noise can be understood as the random change of gray value caused by one or more reasons.
In most cases, smoothing techniques (also commonly referred to as filtering techniques) are used to suppress or remove them. Among them, smoothing techniques with Edge Preserving functions have received more attention.
Common smoothing algorithms include Gaussian smoothing, mean smoothing based on two-dimensional discrete convolution, median based on statistical methods Smoothing, bilateral filtering, guided filtering, etc. with edge-preserving smoothing algorithms.

The following will introduce the technical principle, common applications and implementation of median smoothing in detail.

1. Median smoothing principle

1.1 Related concepts

Median smoothing, similar to convolution, is also a neighborhood operation, but the calculation is not a weighted sum, but performs the gray value of the pixels in the neighborhood Sort, and choose the median value of the group as the output gray value.

1.2 Principle

Suppose the input image is I, the height is R, and the width is C. For any position in the image (r,c ), 0≤r≤R, 0≤c≤C, taking (r,c) as the center, width as W, and height as Neighborhood of >H, where W and H are both odd numbers, sort the gray values of the pixels in the neighborhood, and then take the median value, As the gray value at the (r,c) position of the output image O.

For example, the following image matrix:



Take a 3×3 neighborhood centered at position (1,1), and sort the gray values of the pixels in the neighborhood from small to large:



It can be seen that 141 is the median value of the gray value of the group, then the output image O(1,1)=141, and so on, the gray value of all pixels of the output image will be obtained. Of course, the processing of the edge is the same as the convolution operation learned in the previous chapters, and a variety of strategies can be used, and mirroring the boundary is an ideal choice.

1.3 Function

In image processing, the most important ability of median filtering is to remove salt and pepper noise, which is often used to protect edge information. It is a classic method of smoothing noise. This method is very effective in eliminating salt and pepper noise. Salt and pepper noise refers to isolated white or black spots appearing in the image due to decoding errors and other reasons in the image transmission system.

2. C++ implementation

Next, we will introduce the implementation of median smoothing and its effect.

2.1 Function Introduction

OpenCV does not provide a function to directly calculate the median. You can use the other two functions sort() and reshape() to indirectly calculate the median. Let’s first understand these two functions:

1. sort()

void cv::sort(InputArray src,
OutputArray dst,
int flags
)
parameter Explanation
src input single channel matrix
dst output matrix , the size and data type are consistent with src
flags sorting rules, CV_SORT_EVERY_ROW: for each row Sort; CV_SORT_EVERY_COLUMN: Sort each column; CV_SORT_ASCENDING: Sort in ascending order; CV_SORT_DESCENDING: Sort in descending order

2. reshape()

reshape() function is more interesting. It can not only change the number of channels of the matrix, but also serialize the elements of the matrix. It is a very useful function.

reshape (int cn,
int rows = 0
)

This function has relatively few parameters, but you must be careful when setting it.

parameter Explanation
cn Indicates the number of channels (channels), if it is set to 0, it means to keep the number of channels unchanged, otherwise it will become the set number of channels
rows indicates the number of rows in the matrix. If it is set to 0, it means to keep the original number of rows unchanged, otherwise it will become the set number of rows

For the method of taking the median value of the neighborhood, you need to use the Mat member function reshape() to change the matrix into one row or one column, and then use the sort() function to perform Sort, and finally take the number in the middle position as the median, for example:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cmath>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv){<!-- -->
Mat ImgMatrix = (Mat_<float>(3, 3) << 1, 2, 3, 4, 5, 6,7,8,9);
\t
//Convert ImgMatrix to 1 line, the number of channels remains the same
Mat ImgMatrix_R = ImgMatrix. reshape(1,1);

\t//Sort
Mat dst;
cv::sort(ImgMatrix_R, dst, CV_SORT_EVERY_ROW);

// get median
float medianvalue=dst.at<float>(0, (dst.cols-1) / 2);

cout << "median value is:" << medianvalue << endl;

waitKey(0);

return 0;
\t
}

2.2 Specific implementation

For the median smoothing of the image, in order to save the problem of judging the boundary, it is necessary to perform the operation of expanding the boundary on the input image matrix. The specific code is as follows:

Mat medianSmooth(const Mat & amp;Image, Size size, int borderType = BORDER_DEFAULT){<!-- -->

CV_Assert(Image.type() == CV_8UC1);
int H = size. height;
int W = size. width;
\t
//The height and width of the window are both odd numbers, and the two are generally set to be the same
CV_Assert(H>0 & amp; & amp; W>0);
CV_Assert(H%2==1 & amp; & amp; W%2== 1);

//Extend the boundary of the original image matrix
int h=(H - 1)/2;
int w=(W-1)/2;
Mat ImagePadding;
copyMakeBorder(Image, ImagePadding, h, h, w, w, borderType);
//Input the height and width of the image
int rows = Image.rows;
int cols = Image.cols;
//Output image after median smoothing
Mat medianI(Image. size(), CV_8UC1);
int i=0,j=0;
// position of the median
int index=(H*W - 1)/ 2;
for (int r=h;r< h + rows; r + + )
{<!-- -->
for (int c=w;c<w + cols; c++ )
{<!-- -->
//Take the neighborhood with the current position as the center and size as the size
Mat region = ImagePadding(Rect(c-w,r-h, W,H)).clone();
\t
// Convert this neighborhood to a row matrix
region = region. reshape(1,1);
\t
//sort
cv::sort(region,region,CV_SORT_EVERY_ROW);
\t
// take the median
uchar mValue = region.at<uchar>(0,index);
medianI.at<uchar>(i,j) = mValue;
j + + ;
}
i + + ;
j=0;
}
return median I;
}

The above functions can only handle 8-bit images, and other data types are similar. The code of the main function that uses this function to perform median smoothing on an image is as follows:

int main(int argc, char** argv) {<!-- -->
cv::Mat src = cv::imread("D:/VSCodeFile/OpenCV_CSDN/image/logo_gray.jpeg");
CV_Assert(!src.empty());
src.convertTo(src, CV_8UC1);

// median filter
Mat medianImage=medianSmooth(src,Size(5,5));

imshow("src", src);
imshow("medianImage", medianImage);

waitKey(0);

return 0;
}



Generally speaking, if there are brighter or darker objects in the image, if the object size is smaller than the median smoothing window radius, then they will basically be filtered out, while larger objects will be almost intact. preserved. Therefore, the window size of median smoothing needs to be adjusted according to different problems encountered.

Median smoothing needs to sort all pixels in the neighborhood by gray value, which is generally slower than convolution operation. There are some algorithms that can speed up median smoothing. Such a function is provided in OpenCV:

void cv::medianBlur(InputArray src,
OutputArray dst,
int ksize
)
parameter Explanation
src Input matrix
dst Output matrix whose size is consistent with the data type and src
ksize Core size greater than 1 and odd number

For the above code, here is just a few lines to solve:

```cpp
int main(int argc, char** argv) {<!-- -->
cv::Mat src = cv::imread("D:/VSCodeFile/OpenCV_CSDN/image/logo_gray.jpeg");
CV_Assert(!src.empty());
src.convertTo(src, CV_8UC1);

// median filter
Mat dst;
cv::medianBlur(src, dst, 5);
\t

imshow("src", src);
imshow("dst", dst);

waitKey(0);

return 0;
}



Median smoothing is only one type of sorting statistical smoothing. If you change the median value of the neighborhood to the minimum or maximum value in the neighborhood, it will obviously darken or brighten the image. This kind of method is the basis of morphological processing to be introduced later.

Gaussian smoothing and mean smoothing will make the edge information of the image blurred when removing image noise. Later, we will introduce the smoothing algorithm that can maintain the edge during the image smoothing process. strong>: bilateral filtering and guided filtering.

3. Summary

Finally, to make a long story short, everyone should practice it after reading it. Remember not to be hot for three minutes, fish for three days, and post on the net for two days. OpenCV is a better way to learn the theoretical knowledge of image processing. You can also try to write a blog by yourself to record your usual learning progress. You can communicate and discuss with many scholars on the Internet. If you have any questions, I hope you can actively comment and communicate. I will also update in time to supervise my own learning progress. I hope that you can like, follow and bookmark if you think it is good.

This is the end of today’s article~



If you like it, please like it, bookmark it, follow it~