Android基于OpenCV实现图像金字塔

目录
  • 图像金字塔
    • 高斯金字塔
    • 拉普拉斯金字塔
  • 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图像金字塔的资料请关注我们其它相关文章!

(0)

相关推荐

  • python 用opencv实现图像修复和图像金字塔

    我们将学习如何通过一种称为修复的方法去除旧照片中的小噪音,笔画等.基本思路很简单:用相邻像素替换那些坏标记,使其看起来像邻域. cv2.inpaint() cv2.INPAINT_TELEA cv2.INPAINT_NS import numpy as np import cv2 as cv img = cv.imread('messi_2.jpg') mask = cv.imread('mask2.png',0) dst = cv.inpaint(img,mask,3,cv.INPAINT_T

  • OpenCV 图像金字塔的实现示例

    目录 1.高斯金字塔 2.拉普拉斯金字塔 本文主要介绍了OpenCV 图像金字塔,具有一定的参考价值,感兴趣的可以了解一下 高斯金字塔reduce void cv::pyrDown() expand void cv::pyrUp() 1.高斯金字塔 图像金字塔是对一张输入图像先模糊再下采样为原来的高.宽的1/2,不断重复模糊与下采样的过程就得到了不同分辨率的输出图像,叠加在一起就形成了图像金字塔. 高斯金字塔便是先进行高斯模糊,再进行reduce和expand操作.高斯金字塔中的较高级别(低分辨

  • Android基于OpenCV实现图像金字塔

    目录 图像金字塔 高斯金字塔 拉普拉斯金字塔 API 下采样 上采样 操作 操作 效果 源码 图像金字塔 图像金字塔是图像中多尺度表达的一种,最主要用于图像的分割,是一种以多分辨率来解释图像的有效但概念简单的结构. 图像金字塔最初用于机器视觉和图像压缩,一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低,且来源于同一张原始图的图像集合.其通过梯次向下采样获得,直到达到某个终止条件才停止采样. 金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似. 我们将一层一层的图像比喻成金字塔

  • Android基于OpenCV实现图像修复

    目录 API 操作 图像修复 实际应用中,图像常常容易受损,如存在污渍的镜头.旧照片的划痕.人为的涂画(比如马赛克),亦或是图像本身的损坏.将受到损坏的图像尽可能还原成原来的模样的技术,称之为图像修复.所谓修复,就代表图像大部分内容是完好的,所以,图像修复的原理,就是用完好的部分去推断受损部分的信息,特别是完好部分与受损部分的交界处,即受损区域的边缘,在这个推断过程中尤为重要. OpenCV给我们提供了inpaint方法来实现这个功能,并提供了两种图像修复的算法: 基于Navier-Stokes

  • Android基于OpenCV实现图像脱色

    目录 脱色 原理 API 操作 效果 源码 脱色 Imgproc.cvtColor(rgb, gray, Imgproc.COLOR_RGB2GRAY)可以快速的实现图片脱色,其通过简单的计算将三通道图像转换成单通道图像,经典的灰度转换公式如下: 但是转换过的图像存在对比度丢失,无法区分颜色的问题.OpenCV给我们提供另外一种脱色方法Photo.decolor,旨在最大限度的保留图片对比度. 原理 论文详情:www.cse.cuhk.edu.hk/~leojia/pro- 论文PDF:www.

  • Android基于OpenCV实现非真实渲染

    目录 非真实渲染 API 边缘保留滤波 细节增强 素描铅笔画 风格化 操作 效果 非真实渲染 非真实感渲染(Non Photorealistic Rendering,简称NPR),是指利用计算机模拟各种视觉艺术的绘制风格,也用于发展新的绘制风格.比如模拟中国画.水彩.素描.油画.版画等艺术风格.NPR也可以把三维场景渲染出丰富的.特别的新视觉效果,使它具备创新的功能.NPR渲染以强烈的艺术形式应用在动画.游戏等娱乐领域中,也出现在工程.工业设计图纸中.广阔的应用领域,不仅是由于它的艺术表现形式丰

  • Android基于opencv实现多通道分离与合并

    目录 多通道分离 API 操作 通道合并 API 操作 结果 源码 多通道分离 API public static void split(Mat m, List<Mat> mv) 参数一:m,待分离的多通道图像 参数二:mv,分离后的单通道图像 操作 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mBinding = DataBindingUtil.setConte

  • Android基于OpenCV实现霍夫直线检测

    目录 霍夫直线检测 点和线的对偶性 极坐标参数方程 API 操作 效果 霍夫直线检测 点和线的对偶性 图像空间中的点,对应霍夫空间中的直线 图像空间中的直线,对应霍夫空间中的点 共点的直线,在霍夫空间中对应的点在一条直线上 共线的点,在霍夫空间中对应的直线交于一点 极坐标参数方程 对于平面中的一条直线,在笛卡尔坐标中,常见的有点斜式,两点式两种表示方法.然而在霍夫变换中,考虑的是另外一种表示方式:使用(r, theta)来表示一条直线.其中r为该直线到原点的距离,theta为该直线的垂线与x轴的

  • Android基于OpenCV实现QR二维码检测

    目录 QR二维码 QR二维码格式 QR二维码结构 API QRCodeDetector类结构 检测QR二维码 识别QR二维码 检测并识别QR二维码 操作 结果 源码 QR二维码 QR码(英语:Quick Response Code:全称为快速响应矩阵图码)是二维码的一种,于1994年由日本DENSO WAVE公司发明.QR来自英文Quick Response的缩写,即快速反应,因为发明者希望QR码可以快速解码其内容.QR码使用四种标准化编码模式(数字.字母数字.字节(二进制)和日文(Shift_

  • Android基于OpenCV实现Harris角点检测

    目录 什么是角点? 为什么要检测角点? Harris角点检测 API 操作 效果 源码 什么是角点? 角点就是极值点,即在某方面属性特别突出的点.当然,你可以自己定义角点的属性(设置特定熵值进行角点检测).角点可以是两条线的交叉处,也可以是位于相邻的两个主要方向不同的事物上的点.角点通常被定义为两条边的交点,或者说,角点的局部邻域应该具有两个不同区域的不同方向的边界.常见的角点有: 灰度梯度的最大值对应的像素点: 两条直线或者曲线的交点: 一阶梯度的导数最大值和梯度方向变化率最大的像素点: 一阶

  • Python基于opencv的图像压缩算法实例分析

    本文实例讲述了Python基于opencv的图像压缩算法.分享给大家供大家参考,具体如下: 插值方法: CV_INTER_NN - 最近邻插值, CV_INTER_LINEAR - 双线性插值 (缺省使用) CV_INTER_AREA - 使用象素关系重采样.当图像缩小时候,该方法可以避免波纹出现.当图像放大时,类似于 CV_INTER_NN 方法.. CV_INTER_CUBIC - 立方插值. 函数 cvResize 将图像 src 改变尺寸得到与 dst 同样大小.若设定 ROI,函数将按

  • python 基于opencv 绘制图像轮廓

    图像轮廓概念 轮廓是一系列相连的点组成的曲线,代表了物体的基本外形. 谈起轮廓不免想到边缘,它们确实很像.简单的说,轮廓是连续的,边缘并不全都连续(下图).其实边缘主要是作为图像的特征使用,比如可以用边缘特征可以区分脸和手:而轮廓主要用来分析物体的形态,比如物体的周长和面积等,可以说边缘包括轮廓. 寻找轮廓的操作一般用于二值图像,所以通常会使用阈值分割或Canny边缘检测先得到二值图. 注意:寻找轮廓是针对白色物体的,一定要保证物体是白色,而背景是黑色,不然很多人在寻找轮廓时会找到图片最外面的一

随机推荐