Image corrosion and swelling belong to morphological operations, which are a series of image processing operations based on shape. The basic idea of digital morphology is to measure and extract the corresponding shape in the image by using the structural elements with certain shape, so as to achieve the purpose of image analysis and recognition. Image corrosion and expansion are based on the highlighted part (white). Expansion is to expand the highlighted part, similar to “field expansion”, while corrosion is to corrode the highlighted part, similar to “field encroachment”. The application of expansion corrosion is mainly embodied in eliminating noise, dividing independent elements or connecting adjacent elements, searching for obvious maximum and minimum regions in images and finding image gradients.

Image expansion

The function of image expansion is to enlarge the target image. The operation effect depends on the size and content of structural elements and the properties of logical operation. The image expansion operation can be used to fill some holes in the target area and eliminate the small particle noise contained in the target area.

Expansion algorithm

  • With structural elements, scan every element of the image;
  • Do it with the structure element and its overlaid binary imagewithOperation;
  • If one of them is 1, that element in the resulting image is 1. Otherwise 0.
  • Result: the binary image is enlarged by one circle

[ dst ( x . y ) = max ( x . y ) : element ( x . y ) indicates 0 src ( x + x . y + y ) ] [\texttt{dst} (x,y) = \max _{(x’,y’): \, \texttt{element} (x’,y’) \ne0 } \texttt{src} (x+x’,y+y’)]

Definition of expansion

For sets A and B, the expansion of A with B, with


A B A\bigoplus B

Represents and uses


( B ) z (B)_z

Represents the result obtained after B shifted z. If the intersection of the translated result and A is not empty, then we record the z point, and the set of all z points meeting the above conditions is the result after A is expanded by B. Represented by:


A B = z ( B ) z A indicates A\bigoplus B = | z | (B)_z \bigcap A\neq \varnothing|

Expansion diagram

API

public static void dilate(Mat src, Mat dst, Mat kernel, Point anchor, int iterations, int borderType, Scalar borderValue) 
Copy the code
  • Parameter 1: SRC, the input image to be expanded, the number of channels of the image can be arbitrary, but the data type of the image must be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F

  • Parameter two: DST, the inflated output image, has the same size and data type as the input image SRC

  • Parameter three: kernel, the structural element used for the expansion operation, can be defined by itself or generated using the getStructuringElement() function

  • Parameter 4: Anchor, the location of the center point in the structural element. The default parameter is the geometric center point of the structural element

  • Parameter 5: Iterations, specifies the number of times of inflation. The default value is 1

  • Parameter 6: borderType, pixel extrapolation select logo

  • Parameter 7: borderValue, the boundary value when using boundary invariant extrapolation

public static Mat getStructuringElement(int shape, Size ksize, Point anchor) 
Copy the code
  • Parameter 1: Shape, the type of structure element

    // C++: enum MorphShapes_c
    public static final int
            CV_SHAPE_RECT = 0,  
            CV_SHAPE_CROSS = 1, 
            CV_SHAPE_ELLIPSE = 2, 
            CV_SHAPE_CUSTOM = 100;
    Copy the code
  • Parameter two: ksize, the size of the structure element

  • Parameter 3: Anchor is the location of the center point. The default parameter is the geometric center point of the structural element

About the shape of the structure

  • CV_SHAPE_RECT: rectangular structure element

[ E i j = 1 ] [E_{ij}=1]
  • CV_SHAPE_CROSS: cruciform structural element

[ E i j = { 1 if   i = anchor.y   o r j = anchor.x 0 otherwise ] [E_{ij} = \begin{cases} 1 & \texttt{if } {i=\texttt{anchor.y } {or } {j=\texttt{anchor.x}}} \\0 & \texttt{otherwise} \end{cases}]
  • CV_SHAPE_ELLIPSE: element of an ellipse structure. Inner ellipse of rectangle.

operation

/** * image bloat **@author yidong
 * @date2020/6/24 * /
class DilateActivity : AppCompatActivity() {

    private lateinit var mBinding: ActivityDilateBinding
    private lateinit var mBinary: Mat
    private var mFlag = Imgproc.CV_SHAPE_RECT
        set(value) {
            field = value
            doDilate(value, mSize.toDouble())
        }
    private var mSize = 3
        set(value) {
            field = value
            doDilate(mFlag, value.toDouble())
        }

    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_dilate)
        mBinding.seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar? , progress:Int, fromUser: Boolean) {
                mSize = progress
                mBinding.tvSize.text = progress.toString()
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?).{}override fun onStopTrackingTouch(seekBar: SeekBar?).{}})val bgr = Utils.loadResource(this, R.drawable.opencv)
        mBinary = Mat()
        val gray = Mat()
        Imgproc.cvtColor(bgr, gray, Imgproc.COLOR_BGR2GRAY)
        Imgproc.threshold(gray, mBinary, 125.0.255.0, Imgproc.THRESH_BINARY_INV)
        mBinding.ivLena.showMat(mBinary)
        bgr.release()
        gray.release()
    }

    override fun onCreateOptionsMenu(menu: Menu?).: Boolean {
        menuInflater.inflate(R.menu.menu_dilate, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        mFlag = when (item.itemId) {
            R.id.dilate_cross -> {
                Imgproc.CV_SHAPE_CROSS
            }
            R.id.dilate_ellipse -> {
                Imgproc.CV_SHAPE_ELLIPSE
            }
            else -> Imgproc.CV_SHAPE_RECT
        }
        return true
    }

    private fun doDilate(flag: Int, width: Double) {
        title = "Flag = $flagSize =,${width}X${width}"
        val kernel = Imgproc.getStructuringElement(flag, Size(width, width))
        val result = Mat()
        Imgproc.dilate(mBinary, result, kernel)
        GlobalScope.launch(Dispatchers.Main) {
            mBinding.ivResult.showMat(result)
            result.release()
        }
    }
    
    override fun onDestroy(a) {
        mBinary.release()
        super.onDestroy()
    }
}
Copy the code

The effect

The source code

Github.com/onlyloveyd/…

In addition, you can also search my official account [OpenCV or Android], follow my series of articles and communicate with me.