Android基于OpenCV实现图像金字塔

编辑: admin 分类: Android 发布时间: 2021-11-29 来源:互联网
目录
  • 图像金字塔
    • 高斯金字塔
    • 拉普拉斯金字塔
  • API
    • 下采样
    • 上采样
  • 操作
    • 操作
      • 效果
        • 源码

          图像金字塔

          图像金字塔是图像中多尺度表达的一种,最主要用于图像的分割,是一种以多分辨率来解释图像的有效但概念简单的结构。

          图像金字塔最初用于机器视觉和图像压缩,一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低,且来源于同一张原始图的图像集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。

          金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。

          我们将一层一层的图像比喻成金字塔,层级越高,则图像越小,分辨率越低。

          高斯金字塔

          高斯金字塔的底层为原始图像,每向上一层则是通过高斯滤波和1/2采样得到(去掉偶数行和列)。通过下采样不断的将图像的尺寸缩小,进而在金字塔中包含多个尺度的图像,一般情况下,高斯金字塔的最底层为图像的原图,每上一层就会通过下采样缩小一次图像的尺寸,通常情况尺寸会缩小为原来的一半,但是如果有特殊需求,缩小的尺寸也可以根据实际情况进行调整。由于每次图像的尺寸都缩小为原来的一半,图像尺缩小的速度非常快,因此常见高斯金字塔的层数为3到6层。

          高斯滤波器可以看做一个低通滤波器,那么每经过一次的高斯滤波,图像中仅能够保留某个频率值以下的频率部分,所以高斯金字塔也可以看做一个低通金字塔(每一级只保留某个频率以下的成分)。

          拉普拉斯金字塔

          拉普拉斯金字塔与高斯金字塔正好相反,高斯金字塔通过底层图像构建上层图像,而拉普拉斯是通过上层小尺寸的图像构建下层大尺寸的图像。拉普拉斯金字塔具有预测残差的作用,需要与高斯金字塔联合一起使用,假设我们已经有一个高斯图像金字塔,对于其中的第i层图像(高斯金字塔最下面为第0层),首先通过下采样得到一尺寸缩小一半的图像,即高斯金字塔中的第i+1层或者不在高斯金字塔中,之后对这张图像再进行上采样,将图像尺寸恢复到第i层图像的大小,最后求取高斯金字塔第i层图像与经过上采样后得到的图像的差值图像,这个差值图像就是拉普拉斯金字塔的第i层图像。

          API

          下采样

          public static void pyrDown(Mat src, Mat dst, Size dstsize, int borderType) 
          • 参数一:src,输入待下采样的图像。
          • 参数二:dst,输出下采样后的图像,图像尺寸可以指定,但是数据类型和通道数与src相同,
          • 参数三:dstsize,输出图像尺寸,可以缺省。
          • 参数四:borderType,像素边界外推方法的标志
          // C++: enum BorderTypes
          public static final int
                  BORDER_CONSTANT = 0,
                  BORDER_REPLICATE = 1,
                  BORDER_REFLECT = 2,
                  BORDER_WRAP = 3,
                  BORDER_REFLECT_101 = 4,
                  BORDER_TRANSPARENT = 5,
                  BORDER_REFLECT101 = BORDER_REFLECT_101,
                  BORDER_DEFAULT = BORDER_REFLECT_101,
                  BORDER_ISOLATED = 16;

          默认状态下函数输出的图像的尺寸为输入图像尺寸的一半,但是也可以通过dstsize参数来设置输出图像的大小,需要注意的是无论输出尺寸为多少都应满足下面式中条件。该函数首先将原图像与内核矩阵进行卷积,内核矩阵如下所示,之后通过不使用偶数行和列的方式对图像进行下采样,最终实现尺寸缩小的下采样图像。

          上采样

          public static void pyrUp(Mat src, Mat dst, Size dstsize, int borderType) 
          • 参数一:src,输入待上采样的图像。
          • 参数二:dst,输出上采样后的图像,图像尺寸可以指定,但是数据类型和通道数与src相同,
          • 参数三:dstsize,输出图像尺寸,可以缺省。
          • 参数四:borderType,像素边界外推方法的标志

          操作

          class GLPyramidActivity : CardGalleryActivity() {
          
              override fun buildCards() {
                  val bgr = Utils.loadResource(this, R.drawable.lena)
                  val rgb = Mat()
                  Imgproc.cvtColor(bgr, rgb, Imgproc.COLOR_BGR2RGB)
                  bgr.release()
                  buildGauss(rgb)
                  rgb.release()
              }
          
              private fun buildGauss(source: Mat) {
                  val gaussList = arrayListOf<Mat>()
                  gaussList.add(source)
                  for (i in 0..2) {
                      val gauss = Mat()
                      Imgproc.pyrDown(gaussList[i], gauss)
                      gaussList.add(gauss)
                  }
          
                  for (i in gaussList.indices) {
                      val bitmap = Bitmap.createBitmap(
                          gaussList[i].width(),
                          gaussList[i].height(),
                          Bitmap.Config.ARGB_8888
                      )
                      Utils.matToBitmap(gaussList[i], bitmap)
                      cards.add(Card("Gauss${i}", bitmap))
                  }
                  buildLaplace(gaussList)
              }
          
              private fun buildLaplace(gaussList: List<Mat>) {
                  val laplaceList = arrayListOf<Mat>()
                  for (i in gaussList.size - 1 downTo 1) {
                      val lap = Mat()
                      val upGauss = Mat()
                      if (i == gaussList.size - 1) {
                          val down = Mat()
                          Imgproc.pyrDown(gaussList[i], down)
                          Imgproc.pyrUp(down, upGauss)
                          Core.subtract(gaussList[i], upGauss, lap)
                          laplaceList.add(lap.clone())
                      }
                      Imgproc.pyrUp(gaussList[i], upGauss)
                      Core.subtract(gaussList[i - 1], upGauss, lap)
                      laplaceList.add(lap.clone())
                  }
          
                  for (i in laplaceList.indices) {
                      val bitmap = Bitmap.createBitmap(
                          laplaceList[i].width(),
                          laplaceList[i].height(),
                          Bitmap.Config.ARGB_8888
                      )
                      Utils.matToBitmap(laplaceList[i], bitmap)
                      cards.add(Card("Laplace${i}", bitmap))
                  }
          
                  for (gauss in gaussList) {
                      gauss.release()
                  }
                  for (lap in laplaceList) {
                      lap.release()
                  }
              }
          }

          操作

          class GLPyramidActivity : CardGalleryActivity() {
          
              override fun buildCards() {
                  val bgr = Utils.loadResource(this, R.drawable.lena)
                  val rgb = Mat()
                  Imgproc.cvtColor(bgr, rgb, Imgproc.COLOR_BGR2RGB)
                  bgr.release()
                  buildGauss(rgb)
                  rgb.release()
              }
          
              private fun buildGauss(source: Mat) {
                  val gaussList = arrayListOf<Mat>()
                  gaussList.add(source)
                  for (i in 0..2) {
                      val gauss = Mat()
                      Imgproc.pyrDown(gaussList[i], gauss)
                      gaussList.add(gauss)
                  }
          
                  for (i in gaussList.indices) {
                      val bitmap = Bitmap.createBitmap(
                          gaussList[i].width(),
                          gaussList[i].height(),
                          Bitmap.Config.ARGB_8888
                      )
                      Utils.matToBitmap(gaussList[i], bitmap)
                      cards.add(Card("Gauss${i}", bitmap))
                  }
                  buildLaplace(gaussList)
              }
          
              private fun buildLaplace(gaussList: List<Mat>) {
                  val laplaceList = arrayListOf<Mat>()
                  for (i in gaussList.size - 1 downTo 1) {
                      val lap = Mat()
                      val upGauss = Mat()
                      if (i == gaussList.size - 1) {
                          val down = Mat()
                          Imgproc.pyrDown(gaussList[i], down)
                          Imgproc.pyrUp(down, upGauss)
                          Core.subtract(gaussList[i], upGauss, lap)
                          laplaceList.add(lap.clone())
                      }
                      Imgproc.pyrUp(gaussList[i], upGauss)
                      Core.subtract(gaussList[i - 1], upGauss, lap)
                      laplaceList.add(lap.clone())
                  }
          
                  for (i in laplaceList.indices) {
                      val bitmap = Bitmap.createBitmap(
                          laplaceList[i].width(),
                          laplaceList[i].height(),
                          Bitmap.Config.ARGB_8888
                      )
                      Utils.matToBitmap(laplaceList[i], bitmap)
                      cards.add(Card("Laplace${i}", bitmap))
                  }
          
                  for (gauss in gaussList) {
                      gauss.release()
                  }
                  for (lap in laplaceList) {
                      lap.release()
                  }
              }
          }

          效果

          上面这个拉普拉斯可能看不太清,但是细看是有图像的。让图片宽度充满看看。

          为了看清拉普拉斯金字塔的图像,图片大小本身并非如此

          源码

          github.com/onlyloveyd/…

          以上就是Android基于OpenCV实现图像金字塔的详细内容,更多关于Android OpenCV图像金字塔的资料请关注海外IDC网其它相关文章!

          【本文由:专业的印度服务器 提供,感谢支持】