This is the 7th day of my participation in Gwen Challenge

Contour area and perimeter

Contour area and perimeter are both important statistical features of contour. Contour area refers to the area enclosed by all pixels in each contour, in pixels. Contour perimeter refers to the perimeter of the area surrounded by all pixels in each contour, also in pixels. By analyzing the contour area and perimeter, we can distinguish the size of objects and identify the difference of objects. At the same time, we can also analyze some other contents. For example, there is a fixed relationship between the perimeter and area of the square area, and there is a fixed relationship between the perimeter and area of the circular area. By calculating the contour area and perimeter, and combining these fixed relations, we can get some conclusions.

API

Outline area

public static double contourArea(Mat contour, boolean oriented)
Copy the code
  • Parameter 1: Contour, the pixel point of the contour.
  • Parameter 2: Oriented: Whether the area has a directional flag bit. True indicates directional, false indicates non-directional. The areas of the clockwise and counterclockwise vertices are negative of each other. This parameter defaults to false.

Outline the perimeter

public static double arcLength(MatOfPoint2f curve, boolean closed) 
Copy the code
  • Parameter 1: Curve, pixel point of contour.
  • Parameter 2: closed: indicates whether the contour is closed. True indicates that the contour is closed. False indicates that the contour is not closed. For example, if closed=true then the perimeter =AB+BC+CA and if closed=false then the perimeter =AB+BC.

operation

Combined with the example of “Contour Discovery and Drawing” in the previous part, calculate the area and perimeter of each contour.

** * idong */ ** idong */
class FindContoursActivity : AppCompatActivity() {
    private lateinit var mBinding: ActivityFindContoursBinding
    private lateinit var mSource: Mat
    private var level = 1
        set(value) {
            field = value
            find()
            mBinding.level.text = level.toString()
        }

    private var mFlag = Imgproc.RETR_TREE
        set(value) {
            field = value
            find()
        }

    private var ignoreLevel = true
        set(value) {
            field = value
            find()
        }

    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_find_contours)
        mBinding.ignoreLevel.setOnCheckedChangeListener { _, isChecked ->
            ignoreLevel = isChecked
        }
        val bgr = Utils.loadResource(this, R.drawable.hierarchy)
        mSource = Mat()
        Imgproc.cvtColor(bgr, mSource, Imgproc.COLOR_BGR2RGB)
        mBinding.ivLena.showMat(mSource)
        title = "RETR_TREE"
    }

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

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        title = item.title
        mFlag = when (item.itemId) {
            R.id.retr_external -> Imgproc.RETR_EXTERNAL
            R.id.retr_list -> Imgproc.RETR_LIST
            R.id.retr_ccomp -> Imgproc.RETR_CCOMP
            else -> Imgproc.RETR_TREE
        }
        return true
    }

    private fun find(a) {
        val tmp = mSource.clone()
        val gray = Mat()
        Imgproc.cvtColor(mSource, gray, Imgproc.COLOR_BGR2GRAY)
        Imgproc.GaussianBlur(gray, gray, Size(13.0.13.0), 4.0.4.0)
        val binary = Mat()
        Imgproc.threshold(gray, binary, 170.0.255.0, Imgproc.THRESH_BINARY and Imgproc.THRESH_OTSU)

        val contours = mutableListOf<MatOfPoint>()
        val hierarchy = Mat()
        Imgproc.findContours(
            binary,
            contours,
            hierarchy,
            mFlag,
            Imgproc.CHAIN_APPROX_SIMPLE
        )

        for (i in 0 until contours.size) {
            val area = Imgproc.contourArea(contours[i])
            val source = MatOfPoint2f()
            source.fromList(contours[i].toList())
            val length = Imgproc.arcLength(source, true)
            Log.d(App.TAG, "Outline of the${i}Area:${area}; Circumference:${length}")}if (ignoreLevel) {
            Imgproc.drawContours(
                tmp,
                contours,
                -1,
                Scalar(255.0.0.0.0.0),
                2,
                Imgproc.LINE_AA
            )
        } else {
            Imgproc.drawContours(
                tmp,
                contours,
                -1,
                Scalar(255.0.0.0.0.0),
                2,
                Imgproc.LINE_AA,
                hierarchy,
                level
            )
        }
        mBinding.ivResult.showMat(tmp)
        Log.d(App.TAG, "hierarchy: ${hierarchy.dump()}")
        gray.release()
        binary.release()
        hierarchy.release()
        tmp.release()
    }


    fun increase(v: View) {
        level += 1
    }

    fun decrease(v: View) {
        level -= 1
    }

    override fun onDestroy(a) {
        mSource.release()
        super.onDestroy()
    }
}
Copy the code

The effect

2020-10-02 13:57:57.801 6127-6127/cn.onlyloveyd. Demo D/LearningAndroidOpenCV: Perimeter: 2967.313708305359 2020-10-02 13:57:57.801 6127-6127/cn.onlyloveyd. Demo D/LearningAndroidOpenCV: outline 1 Area: 434496.0; Perimeter: 2861.9411249160767 2020-10-02 13:57:57.802 6127-6127/cn.onlyloveyd. Demo D/LearningAndroidOpenCV: Outline 2 Area: 277124.0; Perimeter: 2381.313708305359 2020-10-02 13:57:57.802 6127-6127/cn.onlyloveyd. Demo D/LearningAndroidOpenCV: outline 3 Area: 252129.0; Perimeter: 2285.9411249160767 2020-10-02 13:57:57.802 6127-6127/cn.onlyloveyd. Demo D/LearningAndroidOpenCV: outline 4 area: 25732.0; Perimeter: 649.3137083053589 2020-10-02 13:57:57.802 6127-6127/cn.onlyloveyd. Demo D/LearningAndroidOpenCV: outline 5 area: 48772.0; Perimeter: 897.3137083053589 2020-10-02 13:57:57.802 6127-6127/cn.onlyloveyd.demo D/LearningAndroidOpenCV: outline 6 area: 10312.0; Perimeter: 1401.313708305359 2020-10-02 13:57:57.802 6127-6127/cn.onlyloveyd. Demo D/LearningAndroidOpenCV: outline 7 Area: 2588.0; Circumference: 489.3137083053589Copy the code

The source code

Github.com/onlyloveyd/…