Android基于OpenCV实现非真实渲染

目录
  • 非真实渲染
  • API
    • 边缘保留滤波
    • 细节增强
    • 素描铅笔画
    • 风格化
  • 操作
  • 效果

非真实渲染

非真实感渲染(Non Photorealistic Rendering,简称NPR),是指利用计算机模拟各种视觉艺术的绘制风格,也用于发展新的绘制风格。比如模拟中国画、水彩、素描、油画、版画等艺术风格。NPR也可以把三维场景渲染出丰富的、特别的新视觉效果,使它具备创新的功能。NPR渲染以强烈的艺术形式应用在动画、游戏等娱乐领域中,也出现在工程、工业设计图纸中。广阔的应用领域,不仅是由于它的艺术表现形式丰富多样,还在于计算机能够辅助完成原本工作量大、难度高的创作工作。 目前,基于三维软件的NPR渲染器相当多,如FinalToon, Il-lustrator, Pencil等,同时还可以借用程序贴图来创建NPR的材质,协助生成手绘风格的图像效果;另外,像Mental Ray,Reyes,Brazil等外挂渲染器都是NPR渲染的解决方案

引用自【百度百科】

API

OpenCV给我们提供了四种非真实渲染的使用场景:边缘保留滤波、细节增强、素描铅笔画、风格化。

边缘保留滤波

public static void edgePreservingFilter(Mat src, Mat dst, int flags, float sigma_s, float sigma_r)
  • 参数一:src,输入图像,8位三通道。
  • 参数二:dst,输出图像,8位三通道。
  • 参数三:flags,边缘保留标志位。
public static final int
        RECURS_FILTER = 1,
        NORMCONV_FILTER = 2;
  • 参数四:sigma_s,邻域大小。取值0~200。
  • 参数五:sigma_r,邻域内被平均的颜色的不相近程度。取值0~1。

细节增强

public static void detailEnhance(Mat src, Mat dst, float sigma_s, float sigma_r)
  • 参数一:src,输入图像,8位三通道。
  • 参数二:dst,输出图像,8位三通道。
  • 参数三:sigma_s,邻域大小。取值0~200。
  • 参数四:sigma_r,邻域内被平均的颜色的不相近程度。取值0~1。

素描铅笔画

public static void pencilSketch(Mat src, Mat dst1, Mat dst2, float sigma_s, float sigma_r, float shade_factor)
  • 参数一:src,输入图像,8位三通道。
  • 参数二:dst1,输出图像,8位单通道,即黑白素描。
  • 参数三:dst2,输出图像,大小类型与输入图像相同,即彩色素描。
  • 参数四:sigma_s,邻域大小。取值0~200。
  • 参数五:sigma_r,邻域内被平均的颜色的不相近程度。取值0~1。
  • 参数六:shade_factor,强度缩放值。取值0~0.1

风格化

public static void stylization(Mat src, Mat dst, float sigma_s, float sigma_r)
  • 参数一:src,输入图像,8位三通道。
  • 参数二:dst,输出图像,8位三通道。
  • 参数三:sigma_s,邻域大小。取值0~200。
  • 参数四:sigma_r,邻域内被平均的颜色的不相近程度。取值0~1。

关于sigma_s和sigma_r:

sigma_s,即Sigma_Spatial,决定平滑量。sigma_r,即Sigma_Range,决定平均值。

典型的平滑滤波器将像素值替换为其相邻像素的加权和。 邻域越大,过滤后的图像看起来越平滑。 邻域的大小与参数sigma_s成正比。但是在边缘保留滤波器里,有两个关键点:1)平滑图片;2)不平滑边缘/颜色边界。换句话说,我们就无法简单地将像素值替换成邻域像素的加权和。而是在邻域内选取和当前像素值相近的像素然后求取平均值,然后替换当前像素值的方式来避免上述问题。所以就需要两个参数来明确范围和颜色相似程度。

操作

/**
 * 非真实渲染
 *
 * @author yidong
 * @date 11/30/20
 */
class NonPhotoRealisticRenderingActivity : AppCompatActivity() {

    private lateinit var mRgb: Mat
    private val mBinding: ActivityNonPhotorealisticRenderingBinding by lazy {
        ActivityNonPhotorealisticRenderingBinding.inflate(layoutInflater)
    }

    private var sigmaR = 10f
        set(value) {
            field = when {
                value > 200f -> {
                    200f
                }
                value < 0f -> {
                    200f
                }
                else -> {
                    value
                }
            }
            mBinding.tvSigmaR.text = sigmaR.toInt().toString(10)
        }
    private var sigmaS = 0.1f
        set(value) {
            field = when {
                value > 1.0f -> {
                    1.0f
                }
                value < 0f -> {
                    0f
                }
                else -> {
                    value
                }
            }
            mBinding.tvSigmaS.text = String.format("%.1f", sigmaS)
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(mBinding.root)

        mRgb = Mat()
        val bgr = Utils.loadResource(this, R.drawable.cow)
        Imgproc.cvtColor(bgr, mRgb, Imgproc.COLOR_BGR2RGB)
        mBinding.ivLena.showMat(mRgb)
    }

    private fun doEdgePreservingFilter(flag: Int) {
        val dst = Mat()
        mBinding.isLoading = true
        GlobalScope.launch(Dispatchers.IO) {
            Photo.edgePreservingFilter(mRgb, dst, flag, sigmaR, sigmaS)
            launch(Dispatchers.Main) {
                mBinding.isLoading = false
                mBinding.ivResult.showMat(dst)
            }
        }
    }

    private fun doDetailEnhance() {
        val dst = Mat()
        mBinding.isLoading = true
        GlobalScope.launch(Dispatchers.IO) {
            Photo.detailEnhance(mRgb, dst, sigmaR, sigmaS)
            launch(Dispatchers.Main) {
                mBinding.isLoading = false
                mBinding.ivResult.showMat(dst)
            }
        }
    }

    private fun doPencilSketch() {
        val dst1 = Mat()
        val dst2 = Mat()
        mBinding.isLoading = true
        GlobalScope.launch(Dispatchers.IO) {
            Photo.pencilSketch(mRgb, dst1, dst2, sigmaR, sigmaS, 0.03f)
            launch(Dispatchers.Main) {
                mBinding.isLoading = false
                mBinding.ivResult.showMat(dst2)
            }
        }
    }

    private fun doStylization() {
        val dst = Mat()
        mBinding.isLoading = true
        GlobalScope.launch(Dispatchers.IO) {
            Photo.stylization(mRgb, dst, sigmaR, sigmaS)
            launch(Dispatchers.Main) {
                mBinding.isLoading = false
                mBinding.ivResult.showMat(dst)
            }
        }
    }

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

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        title = item.title
        when (item.itemId) {
            R.id.photo_edge_preserving_normconv_filter
            -> {
                doEdgePreservingFilter(Photo.NORMCONV_FILTER)
            }
            R.id.photo_edge_preserving_recurs_filter
            -> {
                doEdgePreservingFilter(Photo.RECURS_FILTER)
            }
            R.id.photo_detail_enhance
            -> {
                doDetailEnhance()
            }
            R.id.photo_pencil_sketch
            -> {
                doPencilSketch()
            }
            R.id.photo_stylization
            -> {
                doStylization()
            }
        }
        return true
    }

    fun incSigmaR(view: View) {
        this.sigmaR = this.sigmaR.plus(1.0f)
        if (this.sigmaR > 200.0f) {
            this.sigmaR = 200f
        }
    }

    fun decSigmaR(view: View) {
        this.sigmaR = this.sigmaR.minus(1.0f)
        if (this.sigmaR < 0f) {
            this.sigmaR = 0f
        }
    }

    fun incSigmaS(view: View) {
        this.sigmaS = this.sigmaS.plus(.1f)
        if (this.sigmaS > 1.0f) {
            this.sigmaS = 1f
        }
    }

    fun decSigmaS(view: View) {
        this.sigmaS = this.sigmaS.minus(.1f)
        if (this.sigmaS < 0f) {
            this.sigmaS = 0f
        }
    }
}

效果

以上就是Android基于OpenCV实现非真实渲染的详细内容,更多关于Android OpenCV实现非真实渲染的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android+OpenCV4.2.0环境配置详解(Android studio)

    仅是个人记录,希望能对有需要的给予一些小小的帮助 首先我们肯定是要去到OpenCV的官网下载对应的SDK,并解压得到文件夹(opencv-4.2.0-android-sdk) 其次是NDK环境搭建(双击shift,输入sdk,找到sdk manager,将下面红色框框勾选安装) 创建项目,我选用的是(并不是只有这一选择) 导入Module File->New->Import Module 路径选择**\opencv-4.2.0-android-sdk\OpenCV-android-sdk\sd

  • Android通过Java sdk的方式接入OpenCv的方法

    简述 公司最近要做运动检测和眼球追踪,鉴于资费等因素,最后考虑使用OpenCv的相关Api来来满足业务需求.在使用过程中发现OpenCv的v4.2.0和v4.1.2接入后均存在一些bug,所以最后选择了v4.1.0版本. 接入步骤 一.下载OpenCV Sdk 前往OpenCv官网下载对应的Android v4.1.0版本的sdk. 二.Android Studio 集成OpenCV Sdk 1.Android Studio 下载cmake和ndk 2.Android Studio 新建ndk项

  • 如何在Android上使用opencv

    1.下载OpenCV的Android包并解压缩(https://opencv.org/releases/) 2.创建Android应用或者在现有应用中,导入OpenCV模块 导入目录时选择Opencv Android中的sdk / java目录 3.修改导入的Opencv模块的build.gradle,使compileSdkVersion.buildToolsVersion.minSdkVersion.targetSdkVersion与app的build.gradle中的一致. 4.修改导入Op

  • OpenCV在Android上的应用示例

    一. OpenCV 介绍 OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows.Android和Mac OS操作系统上.它轻量级而且高效--由一系列 C 函数和少量 C++ 类构成,同时提供了Python.Ruby.MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法. 在移动端上使用 OpenCV 可以完成一系列图像处理的工作. 二. OpenCV 在 Android 上的配置 我在项目中使用的 OpenCV 版本是 4.x.

  • android端使用openCV实现车牌检测

    现在,汽车的踪影无处不在,公路上疾驰,大街边临停,小区中停靠,车库里停泊.管理监控如此庞大数量的汽车是个头疼的问题.精明的人们把目光放在车牌上,因为车牌是汽车的"身份证".所以车牌识别成为了焦点,而车牌检测是车牌识别的基础和前提.本篇文章,主要讨论使用openCV实现车牌检测. openCV是开源计算机视觉库,基于计算机视觉与机器学习,提供强大的图像处理能力.我们可以快速集成openCV库到android端,其中一种方式是直接安装openCV Manager,按需使用:启动服务去动态加

  • 使用Android Studio创建OpenCV4.1.0 项目的步骤

    一.OpenCV  OpenCV(开源计算机视觉库)是一个开源的计算机视觉和机器学习软件库,是一个基于C与C++的跨平台计算机视觉处理库. 二.下载 开发基于Andorid的计算机视觉的应用可以使用OpenCV 4.1.0-Android SDK: 从官方网站下载 OpenCV 4.1.0 For Android SDK https://sourceforge.net/projects/opencvlibrary/files/4.1.0/opencv-4.1.0-android-sdk.zip/

  • Android OpenCv4 绘制多边形的方法

    集成非常简单,直接按Module形式导入 sdk 即可 官方地址,打开选择Android 下载完成解压以后直接导入OpenCV-android-sdk目录下的sdk文件即可. 绘制矩形 方法 /** img 输入图像 pt1 左上起点 pt2 右下终点 color 绘制直线的颜色 thickness 直线宽度.若为负值,表示填充 lineType 边界的类型,可取值为FILLED ,LINE_4 ,LINE_8 和LINE_AA shift 点坐标中的小数位数 **/ public static

  • Android 通过cmake的方式接入opencv的方法步骤

    简述 上篇 我们通过Java sdk的方式已经将opencv接入到项目中了,如果想使用opencv sdk 提供的 C++ 头文件与 .so动态库,自己封装jni这样使用上篇的方式显然是不能实现的.所以本篇我们介绍通过cmake的方式接入opencv. 接入步骤 1.新建jni项目 具体创建过程参考上篇:通过Java sdk方式接入opencv. 2.导入so库 在项目app/src/main目录下新建jniLibs,并将解压后的opencv sdk 目录下对应的路径 sdk/native/li

  • Android基于OpenCV实现图像修复

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

  • Android+OpenCv4实现边缘检测及轮廓绘制出图像最大边缘

    实现步骤: 图像灰度化 边缘检测 根据Canny检测得出来的Mat寻找轮廓 算出最大轮廓周长or面积 根据获取到的最大轮廓下标进行轮廓绘制 画出最大矩形,并返回Rect Canny边缘检测 基于Canny算法的边缘检测主要有5个步骤,依次是高斯滤波.像素梯度计算.非极大值像素梯度抑制.滞后阈值处理和孤立弱边缘抑制.Canny在有噪声的情况下表现好不好,取决于前面的降噪过程,可以手动做高斯处理提高识别率. /** image 输入图像,必须是CV_8U的单通道或者三通道图像. edges 输出图像

  • Android Studio4.0导入OpenCv4.3.0的方法步骤

    1.准备环境 Android Studio4.0:官网下载:https://developer.android.google.cn/studio/ (Android Studio安装之前首先需要确认电脑上是否安装好JAVA环境,具体安装可以参考其他大佬,本文不作为重点) OpenCv4.3.0:官网下载:https://opencv.org/ 百度网盘:链接: https://pan.baidu.com/s/1aC2E_LT8yFkyAKgZhcNPbg 提取码: 7bk1 2.新建工程 双击打

随机推荐