Shi-Tomasi角点检测
onlyloveyd 486 4

Shi-Tomasi角点检测

在Harris角点检测中,Harris角点评价系数R表示为: $$ R=det(M)-k(trace(M))^2 $$

$$ det(M)=λ_1λ_2 $$

$$ trace(M)=λ_1+λ_2 $$

$$ 其中det(M)=λ_1λ_2是矩阵的行列式,trace(M)=λ_1+λ_2是矩阵的迹 $$

λ1 和 λ2 是矩阵M的特征值, k是一个经验常数,在范围 (0.04, 0.06) 之间。由于 Harris 角点检测算法的稳定性和 k 值有关,而 k 是个经验值,不好设定最佳值,且角点的稳定性与矩阵 M 的较小特征值有关,于是直接用较小的那个特征值作为评价系数。所以在Shi-Tomasi算法中,评价系数R表示为: $$ R=min(λ_1,λ_2) $$

如果某个像素点R值大于阈值,则像素点是为角点。把它绘制到 λ1 ~ λ2 空间中,就会得到下图:

Shi-Tomasi角点检测

API

public static void goodFeaturesToTrack(Mat image, MatOfPoint corners, int maxCorners, double qualityLevel, double minDistance, Mat mask, int blockSize, boolean useHarrisDetector, double k)
  • 参数一:image,输入源图像。必须是单通道8U或者32F类型。
  • 参数二:corners,检测到的角点输出量。
  • 参数三:maxCorners,返回角点数目最大值。如果实际检测到的角点大于返回数目最大值,则返回最强的maxCorners个角点。若此参数设置为0,则无此限制。
  • 参数四:qualityLevel,表示图像角点的最低可接受水平。比如最强角点评价系数为1500,并且此参数为0.01,那么所有评价系数低于15的将都会被排除在外,不是角点,即15就是检测角点的阈值。
  • 参数五:minDistance,角点之间的最小欧几里得距离。
  • 参数六:mask,掩码矩阵,表示检测角点的区域。如果参数不为空,则必须是和源图像大小相同的单通道8U图像。
  • 参数七:blockSize,计算梯度协方差矩阵的尺寸。
  • 参数八:useHarrisDetector,是否使用Harris角点检测。默认为false,使用Shi-Tomasi算法。
  • 参数九:k,Harris角点检测过程中的权重系数。

操作

/**
 * Shi-Tomas角点检测
 * author: yidong
 * 2021/1/7
 */
class ShiTomasiActivity : AppCompatActivity() {

    private val gray by lazy {
        getBgrFromResId(R.drawable.lena).toGray()
    }
    private val rgb by lazy {
        getBgrFromResId(R.drawable.lena).toRgb()
    }
    private val mBinding: ActivityShiTomasBinding by lazy {
        ActivityShiTomasBinding.inflate(layoutInflater)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(mBinding.root)
        mBinding.ivLena.showMat(gray)
        wrapCoroutine({ showLoading() }, { doShiTomas() }, { hideLoading() })
    }

    private fun doShiTomas() {
        val corners = MatOfPoint()
        val maxCorners = 100;
        val qualityLevel = 0.1
        val minDistance = 0.04

        Imgproc.goodFeaturesToTrack(
            gray,
            corners,
            maxCorners,
            qualityLevel,
            minDistance,
            Mat(),
            3,
            false
        )
        val points = corners.toList()
        val result = rgb.clone()
        GlobalScope.launch(Dispatchers.Main) {
            for (point in points) {
                Imgproc.circle(result, point, 10, Scalar(0.0, 255.0, 0.0), 2, Imgproc.LINE_8)
            }
            mBinding.ivResult.showMat(result)
        }
    }

    private fun showLoading() {
        mBinding.isLoading = true
    }

    private fun hideLoading() {
        mBinding.isLoading = false
    }

    override fun onDestroy() {
        super.onDestroy()
        gray.release()
        rgb.release()
    }
}

效果

Shi-Tomasi角点检测

源码

https://github.com/onlyloveyd/LearningAndroidOpenCV

评论区

索引目录