Android OpenCV(九):LUT查找表

1,374 阅读2分钟

LUT查找表

LUT查找表,即像素灰度值的映射表,它以像素灰度值作为索引,以灰度值映射后的数值作为表中的内容。可以类比为我们编程过程中使用的Map,Key为像素灰度值,Value为灰度值映射后的数值。

API

public static void LUT(Mat src, Mat lut, Mat dst)
  • 参数一:src,输入图像矩阵,其数据类型只能是CV_8U
  • 参数二:lut,256个像素灰度值的查找表,单通道或者与src通道数相同
  • 参数三:dst,输出图像矩阵,其尺寸与src相同,数据类型与lut相同

若第二个参数为单通道,则输入变量中的每个通道都按照一个LUT查找表进行映射。如果第二个参数是多通道,则输入变量中的第i个通道按照第二个参数的第i个通道LUT查找表进行映射。函数输出图像的数据类型不与原图像的数据类型保持一致,而是和LUT查找表的数据类型保持一致,这是因为将原灰度值映射到新的空间中,因此需要与新空间中的数据类型保持一致。

操作

class LutActivity : AppCompatActivity() {
    private lateinit var mBinding: ActivityLutBinding
    private lateinit var mRgb: Mat
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_lut)

        mRgb = Mat()
        val bgr = Utils.loadResource(this, R.drawable.lena)
        Imgproc.cvtColor(bgr, mRgb, Imgproc.COLOR_BGR2RGB)
        showMat(mRgb)
        bgr.release()

        mBinding.btLutMulti.setOnClickListener {
            doLutMulti()
        }

        mBinding.btLutSingle.setOnClickListener {
            doLutSingle()
        }
    }

    private fun doLutSingle() {
        val lutOneByteArray = ByteArray(256)
        for (i in 0..255) {
            if (i in 0..100) lutOneByteArray[i] = 0
            if (i in 101..200) lutOneByteArray[i] = 100
            if (i > 200) lutOneByteArray[i] = 255.toByte()
        }
        val lutTable = Converters.vector_uchar_to_Mat(lutOneByteArray.toList())
        val result = Mat()
        Core.LUT(mRgb, lutTable, result)
        showMat(result)
    }

    private fun doLutMulti() {
        val lutOneByteArray = ByteArray(256)
        for (i in 0..255) {
            if (i in 0..100) lutOneByteArray[i] = 0
            if (i in 101..200) lutOneByteArray[i] = 100
            if (i > 200) lutOneByteArray[i] = 255.toByte()
        }
        val lutOne = Converters.vector_uchar_to_Mat(lutOneByteArray.toList())

        val lutTwoByteArray = ByteArray(256)
        for (i in 0..255) {
            if (i in 0..100) lutOneByteArray[i] = 0
            if (i in 101..150) lutOneByteArray[i] = 100
            if (i in 151..200) lutOneByteArray[i] = 150.toByte()
            if (i > 200) lutOneByteArray[i] = 255.toByte()
        }

        val lutTwo = Converters.vector_uchar_to_Mat(lutTwoByteArray.toList())

        val lutThreeByteArray = ByteArray(256)
        for (i in 0..255) {
            if (i in 0..100) lutOneByteArray[i] = 100
            if (i in 101..200) lutOneByteArray[i] = 200.toByte()
            if (i > 200) lutOneByteArray[i] = 255.toByte()
        }
        val lutThree = Converters.vector_uchar_to_Mat(lutThreeByteArray.toList())

        val lutTable = Mat()
        Core.merge(listOf(lutOne, lutTwo, lutThree), lutTable)
        lutOne.release()
        lutTwo.release()
        lutThree.release()

        val result = Mat()
        Core.LUT(mRgb, lutTable, result)
        showMat(result)

        lutTable.release()
        result.release()
    }


    private fun showMat(source: Mat) {
        val bitmap = Bitmap.createBitmap(source.width(), source.height(), Bitmap.Config.ARGB_8888)
        Utils.matToBitmap(source, bitmap)
        mBinding.ivLena.setImageBitmap(bitmap)
    }

    override fun onDestroy() {
        mRgb.release()
        super.onDestroy()
    }
}

结果

源码

github.com/onlyloveyd/…

本文使用 mdnice 排版