
对日本感兴趣的男性朋友应该都知道,日本的AV产业非常发达,几乎每天都会有新的企划诞生,种类非常丰富。可以说不管是多么硬核的“性趣”,日本的AV界总能想办法满足到。但是与其他国家的AV相比,日本的AV有一个很明显的特征,那就是日本的AV会有马赛克。欧美网站上大多都是“无修正”的影片,如果想在这些网站上找到有马赛克的影片反而是一件难事。究竟为什么日本的AV会有马赛克呢?今天,我想分析一下其中的原因。
我先说结论吧。日本的AV有马赛克的原因是——“添加马赛克之后,就可以当没有实际插入”。虽然大家都知道,马赛克盖住的画面肯定就是那些不可描述的画面。但是添加了马赛克之后,“完全是演技”这样的狡辩就说得通了。
那么为什么不给观众们看到实际的性行为,而是要以“演技”这种形式呈现给大家呢?这与3部法律有关系。首先第一部是《卖淫防止法》。以前我在“为什么卖淫违法,但是风俗业却发展得很好”这篇文章中有提到过。这是一部禁止“与金钱挂钩的性行为”的法律。如果AV没有马赛克,明显能看到性行为的发生的话,就可以视为“向女性支付金钱作为此次性行为的报酬”。这样就触及《卖淫防止法》了。所以添加马赛克之后,就可以说“这位女性只是在做性行为的演技而已”,那么对她支付的金钱就不是对于性行为的报酬,而是对于出演这部影片的报酬了。出演AV的女性被称为“AV女演员”或者“性感女演员”,把她们称为“女演员”也是因为这一点。
第二部相关的法律是《猥亵物陈列罪》。顾名思义,这部法律是对于“公然展示猥亵物”这一行为的管制法律。关于这里的“猥亵物”的定义,男性性器官以及女性性器官属于定义内的范畴。而女性的胸部则不属于范畴之内,所以就不需要给胸部打马赛克了。这第二部法律的应对方法就简单了。如果画面上有性器官就违法,那遮住就完事了。
第三部相关的法律是《职业安定法》。因为这部法律有比较多模糊,不明确的地方,我对它的解释有可能不太正确,大家听听就好。这部法律禁止派遣或从事包含“对于公众道德有害的业务”的工作。那么AV属于“对于公众道德有害的业务”吗?这点很关键。先说结论,这属于“灰色领域”,没有明确的标准。实际上裁判所曾经有过“AV女优毫无疑问是对于公众道德有害的业务”的判决。但是现实是,有不少因“强制女性出演AV”而被逮捕的人,但是没有因“出演AV”而被逮捕的女性。现状是,出演AV这件事情本身是不会惊动到警察的,AV女优可以说已经被认定为一种职业了。但是如果不添加马赛克,出演AV就属于对公众道德有害的范畴之内了,所以是有可能会被认定为是犯罪的。为了避免这种情况,马赛克还是有必要的。
因为以上种种原因,对于日本的AV来说马赛克是必要的。实际上也有专门对AV里的马赛克进行审查的部门。这些部门的人从早到晚把AV从头看到尾,审查影片里的马赛克有没有符合标准。还有的人是正职做这个的,在求人网站上也能看到“成人影片审查人员”的招聘信息。我看了相关的招聘信息,25岁入职的人年薪是400万日元,比日本的平均年薪还要高。每天只看AV就能拿到工资,似乎对于男性来说是梦幻般的工作,但做这样的工作并不能学到对社会有贡献的技能,不到一周估计就看饱了,我很怀疑他们在日常生活中还能不能兴奋起来……
看到这里的人,可能会有这样的疑问——的确大多数的成人影片都有马赛克,但是也有无修正的片子啊。的确是这样的,而且看这些影片也不是违法的。那是因为“国外的成人网站”的存在。在一些国家,无修正影片是合法的,在这些国家的网站播放,自然不会触及日本的法律,在日本看这些网站也不是违法的。我在这篇文章中列举的三部法律,都是对制作发行方的管制法律,并没有对观看影片的人进行法律约束。所以在日本观看这些合法的外国网站是没有问题的。而且警视厅也认为“只要以个人行乐为目的的话,是不会触犯法律的”。所以观看影片的人基本上不需要有任何的担心。
大家觉得怎么样?今天我从理论的角度论述了“日本的AV为什么会有马赛克”这个问题。其实“加了马赛克就可以当作没有性行为发生”这种理论,无论是谁都不会相信的,说到底只是大家都默许这种形式的存在罢了。
OpenCV知识总结来到了下一个难度高一点的,掩码 *** 作和模糊效果,这是图像处理里面常见的 *** 作。如果遇到问题请在这里联系我: https://www.jianshu.com/p/67324fb69074
掩码 *** 作实际上思想上很简单:根据一个掩码矩阵(卷积核)重新计算图像中的每一个像素。掩码矩阵中的值表示近邻像素的值(包括自身像素的值)对新像素的值有多大的影响,从数学上观点看来,就是对掩码矩阵内每一个设置好权重,然后对对应的像素领域内做一个权加平均。
卷积是什么?用一个简单的公式来表示:
本质上,卷积就是这种思想。卷积把万事万物看成一个输入,当万事万物的状态出现了变化,则会通过某种系统产生变化,变成另一种输出状态。而这个系统往往就在数学眼里就叫做卷积。
而在深度学习中,往往每一个卷积核是一个奇数的矩阵,做图像识别的时候会通过这个卷积核做一次过滤,筛选出必要的特征信息。
那么掩码 *** 作在数学上是怎么回事?我们平常运用掩码做什么?在OpenCV中掩码最常见的 *** 作就是增加图片对比度。对比度的概念是什么,在上一节聊过,通俗来讲就是能够增强像素之间的细节。我们可以对对每个像素做如下 *** 作:
可能这幅图,理解起来比较困难。实际上流程如此:
举个例子,就以计算出掩码矩阵之后的E的位置,能看到此时是原图中所有的像素都会取出和掩码矩阵一样大小的矩阵。也就是取出原图的红色那一块的领域,分别对E周边包括自己做了一次加权处理,最后赋值回E中。
并且进行如下的权加公式:
这样就能对原来的矩阵进行掩码处理。但是这么做发现没有,如果我们要对A做掩码处理就会发现掩码矩阵对应到原图的位置不存在。现在处理有两种,一种是不对边缘的像素做掩码处理,另一种是为周边的图像做一个padding处理,这种 *** 作在深度学习的图像处理中很常见,通常设置0像素,或者拷贝对边的边缘像素。
能看到这里处理和卷积处理不太一样,只是为了方便,把这种掩码滤波 *** 作称为一种核,是自相关,并不是去计算卷积。
能看到此时这两张图片的对比度有很明显的区别。经过掩码矩阵之后,会发现原图会更加平滑一点,而掩码 *** 作之后会导致整个图片最亮和最暗之间的差距拉大。
从数学公式上来看,当前像素权重为5,周边的点的权重是-1和0.能够发现会对当前的节点加深,同时把周围的像素值减掉,就增加了每一个像素点和周边像素差值,也就是对比度。
当然在OpenCV中,有这么一个函数filter2D,处理掩码 *** 作。
这里创建一个3*3的核。这个核实际上就是上图的那个。这样传递一个掩码矩阵和图像的深度就完成了掩码 *** 作。
平滑也称为模糊,是一项高频率使用的 *** 作。
平滑的作用有很多,其中一项就是降噪音。平滑处理和掩码 *** 作有点相似,也是需要一个滤波器,我们最常用的滤波器就是线性滤波器。线性滤波处理的输出像素值 是输出像素值 的权加和:
其中,h(k,l)成为核,它仅仅只是一个权加系数。图形上的 *** 作和上面的图相似。不妨把核当成一个滑动窗口,不断的沿着原图像素的行列扫动,扫动的过程中,不断的把路过像素都平滑处理。
这里先介绍均值滤波器,它的核心如下:
这里的参数意思是,src:输入的图像,dst:经过均值模糊之后的输出图像,Size:是指这个滤波器的大小,Point是指整个图像模糊绕着哪个原点为半径的进行处理,传入(-1,-1)就是指图像中心,这样就能模糊整个图像。
其计算原理很简单就是,把核里面的所有权重设置为1,最后全部相加求平均值。最后赋值到原来的像素上。
最有用的滤波器 (尽管不是最快的)。 高斯滤波是将输入数组的每一个像素点与 高斯内核 卷积将卷积和当作输出像素值。
高斯模糊实际上是一个二维的高斯核。回顾一下一维的高斯函数:
那么二维实际上就是,就是在原来的x,y轴的情况下,增加一个z轴的纬度,实际上看起来就像一座山一样。
二维的高斯函数可以表示为:
为了达到达到
其OpenCV的调用方式:
这里的参数意思是,src:输入的图像,dst:经过高斯模糊之后的输出图像,Size:是指这个滤波器的大小。sigmaX和sigmaY分别指代的是高斯模糊x轴上和y轴上的二维高斯函数的变化幅度。
换个形象的话说,用上图举个例子,就是确定这个高斯函数这个山的x方向的陡峭程度以及y轴方向的陡峭程度。
下面就高斯模糊,均值模糊和原图的比对
能看到,高斯模糊比起均值模糊保留了图像中相关的形状信息。
为什么会这样呢?原因很简单。因为在计算高斯模糊之前,会根据当前像素区域中所有的像素点进行一次,核的计算,越往中心的权重越高,权重如同小山一下,因此中心的像素权重像素一高了,虽然模糊但是还是保留了原来的形状。
但是当高斯模糊的矩阵大小和sigmaX,sigmaY相似的时候,整个高斯函数就不像山,而是想平原一样平坦。换句话说,整个高斯核中的权重就会,偏向一,就会导致和均值模糊类似效果。
高斯模糊计算流程:
图像中某一段图形的像素是如下分布,
这个时候高斯模糊需要一个核去对每一个位置做滤波。此时不同于均值模糊,没有固定的核矩阵,而是通过上面这个矩阵,计算出高斯的核,最后再计算变化后的矩阵每一个对应的像素。
虽然原理是这样,但是实际上OpenCV为了迅速,在原生实现的时候,内部判断到核是小于7的大小,设置一套固定的高斯模糊矩阵。
这样直接就结束,不是我文章的风格,作为一个程序员,还是有必要探索一下,为什么OpenCV计算速度会比我们自己手写的快。
为了让源码看的不那么辛苦,先聊聊OpenCV底层的设计思想。首先在OpenCV中,内置了几种计算方案,按照效率高低优先度依次的向后执行。
这种设计可以看成我们的平常开发的拦截器设计。当发现优先度高的计算模式发现可以使用的时候,OpenCV将会使用这种模式下的算法进行运算。
一般来说,OpenCV内置如下四个层级计算方案,按照优先顺序依次为:
能看到按照这个优先级不断的向下查找,找到当前OpenCV最快的计算环境。除了最后一个之外,其他三个都是并发计算。
记住这个流程,我们查看OpenCV的源码就很轻松了。
先来看看filter2D的源码。
果不其然,在filter2D实现的第一步,就开始调用CV_OCL_RUN宏去调用OpenCL的显卡并发计算。
能看到,这里面发送了一个condition和一个方法到OpenCL中运行。但是如果,OpenCV在编译的时候,我们没有打开这个OpenCL的选项,没有OpenCL的环境的时候,它实际上就是一个没什么用处的宏:
当有了OpenCL的环境,这个宏就会替换成这个:
能清晰的看到,此时会判断当前的OpenCL是否还在活跃,活跃的状态,并且条件和方法符合规范,就会通过CV_IMPL_ADD,把方法添加到一个vector向量中,让OpenCL读取执行。
在这里面,OpenCV想要使用OpenCL进行计算,就需要这个Mat的类型是UMat,并且是纬度小于等于2.当不符合这两个条件将不会执行OpenCL。
UMat是专门给OpenCL规范计算而使用的矩阵。里面有很多和Mat相似的方法。
此时可能是多线程处理,因此会添加一个智能锁,去保证数据的正确性。
具体的思路,将不作为重点,这边先看看OpenCV是传入了ocl_filter2D的方法,看看这个方法在OpenCL中的执行流程。
OpenCL会把命令最后发送到显卡处理。
实际上这一步和上面的方法有点相似。本质上都是获取需要模糊的区域,如果是(-1,-1),则取中心点,接着判断当前滤波对边缘的处理(BORDER_ISOLATED 不去获取Point为圆心设置的模糊之外的区域)。
能看到这个枚举已经解释很清楚了,默认的边缘处理是复制二个和倒数第二个填充边缘。
最后进入到hal的filter2D进一步 *** 作。
能看到这里有四种方式:
在情况1中,一般的情况replacementFilter2D返回的是一个没有实现的错误码,第二种情况是Intel的并行计算库,没有任何研究,跳过。我们来看看第三种情况和第四种情况
当然这里面判断能够使用dft的判断首先要当前必须要整张图做滤波处理,其次是不能是(0,0)的点为圆心做滤波。最后要判断当前当前的cpu指令是否支持,支持则允许核的宽 高最高为130以内使用原生实现,否则只支持核的宽 高为50以内使用原生实现。
能看到这里面的核心就是调用crossCorr,处理核以及原图的矩阵(使用了快速傅立叶处理相关性计算)。最后从同add添加到目标Mat中,由于add的delta函数为0,因此就和替代的效果一致。
能看到此时,先初始化一个FilterEngine(线性滤波引擎),接着使用apply调用滤波引擎的执行方法。
我们来看看线性引擎的创建:
实际上在这个过程中通过makePtr创建一个sharedptr的指针指向FilterEngine,其原理和Android的智能指针相似。
这个引擎不是关键关键的是getLinearFilter,这个方法创建了一个线性滤波器的实际 *** 作对象。
我们来看看这个结构体:
能看到这里面会根据次数传进来的目标矩阵和原始矩阵的位深创建不同的滤波 *** 作者。
假设,我们现在原图和目标图都是8位位深的矩阵,我们只需要关注下面这个构造函数。
Fliter2D结构体持有着模糊中心点,核,原/目标矩阵, 可以猜测到实际上正在做 *** 作的就是这个结构体。
在preprocess2DKernel方法中,Fliter2D把核的相关信息存储到coords,coeffs中
可以看到此时会判断当前的核矩阵中type是什么,接着再把矩阵中每一个不为0的位置设置进coords,像素数值设置到_coeffs。此时相当于把核矩阵展开成一个向量。
能看到此时滤波引擎会先调用FilterEngine__start,再调用FilterEngine__proceed执行计算。
实际上在FilterEngine__start中计算的是本次循环,需要计算的边界。
FilterEngine__proceed中才是正式计算,做dst循环,最后把具体 *** 作丢给线性引擎生成的Fliter2D的方法中。
了解这两个东西我们直接抽出核心看看fliter是如何运作:
如何在Android程序中使用OpenCV有两种方式(重点讲后面一种):
1.使用OpenCV Java API。
OpenCV安装路径“F:\OpenCV-2.3.1-android-bin”下有两个文件夹,
将文件夹“OpenCV-2.3.1”拷贝到你的Eclipse工作空间所在的目录,也就是在你的项目的上一级目录中,然后导入到工作空间中,在Package Explorer中选择你的项目,单机右键在d出菜单中选择Properties,然后在d出的Properties窗口中左侧选择Android,然后点击右下方的Add按钮,选择OpenCV-2.3.1并点击OK,
此时,展开你的项目树,你可以看到新加了一个OpenCV-2.3.1_src目录,如下图,那么就是正确添加了OpenCV Java API,否则就是你放置OpenCV-2.3.1的目录路径不正确。
然后就可以在你的Java源文件中导入OpenCV的API包,并且使用OpenCV API了,OpenCV API的包的形式如下:
Org.opencv.(OpenCV模块名)。(OpenCV类名)
例如:
Org.opencv.core.Mat
2.利用JNI编写C++ OpenCV代码,通过Android NDK创建动态库(。so)
新建一个工作空间,例如“TestOpenCV”,在Window->Preferences中设置好Android SDK的路径。
然后新建一个Android项目,Build Target选择Android2.2,命名为“HaveImgFun”,活动名改为HaveImgFun,Package name中填写com.testopencv.haveimgfun,最后点击finish。
如同使用OpenCV Java API那样,将OpenCV-2.3.1文件夹拷贝到与工作空间同一级目录中;另外,将“F:\OpenCV-2.3.1-android-bin\samples”下的includeOpenCV.mk文件拷贝到和项目HaveImgFun同一级目录中:
(上面这个各个文件夹和文件的放置很重要,因为OpenCV-2.3.1下的OpenCV.mk中有很多相对路径的指定,如果不是这样放置,在NDK生成动态库时可能会报文件或文件夹无法找到的错误)
选择Package Explorer中你的项目,右键选择new->folder,新建一个名为jni的文件夹,用来存放你的c/c++代码。
然后把res->layout下的main.xml的内容改为下面所示:
1 <?xml version=“1.0” encoding=“utf-8”?>2 <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android” 3 android:orientation=“vertical” 4 android:layout_width=“fill_parent” 5 android:layout_height=“fill_parent” 6 >7 <Button android:layout_height=“wrap_content” 8 android:layout_width=“fill_parent” 9 android:id=“@+id/btnNDK” 10 android:text=“使用C++ OpenCV进行处理” />11 <Button android:layout_height=“wrap_content” 12 android:layout_width=“fill_parent” 13 android:id=“@+id/btnRestore” 14 android:text=“还原” /> 15 <ImageView android:id=“@+id/ImageView01” 16 android:layout_width=“fill_parent” 17 android:layout_height=“fill_parent” /> 18 </LinearLayout>
上面的代码就是一个线性布局里面包含2个按钮加上一个显示图像的ImageView
在文件夹src下的com.testopencv.haveimgfun包中新建一个类用于包装使用了opencv c++代码的动态库的导出函数,类名为LibImgFun。
Eclipse会为你创建一个新的文件LibImgFun.java,将里面的内容改为:
1 package com.testopencv.haveimgfun2 public class LibImgFun { 3 static { 4 System.loadLibrary(“ImgFun”); 5} 6 /** 7 * @param width the current view width 8 * @param height the current view height 9 */ 10 public static native int[] ImgFun(int[] buf, int w, int h); 11 }
从上面的代码可以得知,我们的动态库名字应该为“libImgFun.so”,注意“public static native int[] ImgFun(int[] buf, int w, int h)”中的native关键字,表明这个函数来自native code。static表示这是一个静态函数,这样就可以直接用类名去调用。
在jni文件夹下建立一个“ImgFun.cpp”的文件,内容改为下面所示:
1 #include <jni.h>2 #include <stdio.h>3 #include <stdlib.h>4 #include <opencv2/opencv.hpp>5 using namespace cv6 7 extern “C”8 { 9 JNIEXPORT jintArray JNICALL Java_com_testopencv_haveimgfun_LibImgFun_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h); 10 JNIEXPORT jintArray JNICALL Java_com_testopencv_haveimgfun_LibImgFun_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h){ 11 12 jint *cbuf13 cbuf = env->GetIntArrayElements(buf, false); 14 if(cbuf == NULL) 15 { 16 return 017 } 18 19 Mat myimg(h, w, CV_8UC4, (unsigned char*)cbuf); 20 for(int j=0j<myimg.rows/2j++) 21 { 22 myimg.row(j)。setTo(Scalar(0,0,0,0)); 23 } 24 25 int size=w * h26 jintArray result = env->NewIntArray(size); 27 env->SetIntArrayRegion(result, 0, size, cbuf); 28 env->ReleaseIntArrayElements(buf, cbuf, 0); 29 return result30 } 31 }
上面的代码中#include <jni.h>是必须要包含的头文件,#include <opencv2/opencv.hpp>是opencv要包含的头文件。
动态库要导出的函数如下声明:
JNIEXPORT jintArray JNICALL Java_com_testopencv_haveimgfun_LibImgFun_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h);
JNIEXPORT 和JNICALL是必须要加的关键字
jintArray就是int[],这里返回类型要么为空,要么为jni中定义的类型,事实上就是C\C++类型前面加上j,如果是数组,则在后面加上Array。
函数名的命名规则如下:
Java_(包路径)_(类名)_(函数名) (JNIEnv *env, jobject obj, 自己定义的参数…)
包路径中的“.”用“_”(下划线)代替,类名就是上面包装该动态库函数的类的名字,最后一个才是真正的函数名;JNIEnv *env和jobject obj这两个参数时必须的,用来调用JNI环境下的一些函数;后面就是你自己定义的参数。在这里,jintArray buf代表了传进来的图像的数据,int w是图像的宽,int h是图像的高。
这个函数的功能是将传进来的图像的上半部分涂成黑色。
然后再在jni下新建两个文件“Android.mk”文件和“Application.mk”文件,这两个文件事实上就是简单的Makefile文件。
其中将Android.mk的内容改为如下所示:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include /includeOpenCV.mk
ifeq (“$(wildcard $(OPENCV_MK_PATH))”,“”)
#try to load OpenCV.mk from default install location
include $(TOOLCHAIN_PREBUILT_ROOT)/user/share/OpenCV/OpenCV.mk
else
include $(OPENCV_MK_PATH)
endif
LOCAL_MODULE:= ImgFun
LOCAL_SRC_FILES := ImgFun.cpp
include $(BUILD_SHARED_LIBRARY)
Application.mk的内容改为如下所示:
APP_STL:=gnustl_static
APP_CPPFLAGS:=-frtti -fexceptions
APP_ABI:=armeabi armeabi-v7a
其中APP_ABI指定的是目标平台的CPU架构。(经过很多测试,android2.2必须指定为armeabi,android2.2以上的使用armeabi-v7a,如果没有设置对,很有可能安装到android虚拟机失败,当然你同时如上面写上也是可以的)
上面的步骤完成后,就可以使用NDK生成动态库了,打开cygwin,cd到项目目录下:
输入$NDK/ndk-build命令,开始创建动态库。
这时候刷新Eclipse的Package Explorer会出现两个新的文件夹obj和libs。
现在,只剩最后一步完成这个测试程序。
将一张图片,例如“lena.jpg”放到项目res->drawable-hdpi目录中并刷新该目录。
然后将HaveImgFun.java的内容改为下面所示:
1 package com.testopencv.haveimgfun2 3 import android.app.Activity 4 import android.graphics.Bitmap 5 import android.graphics.Bitmap.Config 6 import android.graphics.drawable.BitmapDrawable 7 import android.os.Bundle 8 import android.widget.Button 9 import android.view.View 10 import android.widget.ImageView 11 12 public class HaveImgFun extends Activity{ 13 /** Called when the activity is first created. */ 14 ImageView imgView 15 Button btnNDK, btnRestore16 17 @Override 18 public void onCreate(Bundle savedInstanceState) { 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.main); 21 22 this.setTitle(“使用NDK转换灰度图”); 23 btnRestore=(Button)this.findViewById(R.id.btnRestore); 24 btnRestore.setOnClickListener(new ClickEvent()); 25 btnNDK=(Button)this.findViewById(R.id.btnNDK); 26 btnNDK.setOnClickListener(new ClickEvent()); 27 imgView=(ImageView)this.findViewById(R.id.ImageView01); 28 Bitmap img=((BitmapDrawable) getResources()。getDrawable(R.drawable.lena))。getBitmap(); 29 imgView.setImageBitmap(img); 30 } 31 32 class ClickEvent implements View.OnClickListener{ 33 public void onClick(View v){ 34 if(v == btnNDK){35 long current=System.currentTimeMillis(); 36 Bitmap img1=((BitmapDrawable) getResources()。getDrawable(R.drawable.lena))。getBitmap(); 37 int w=img1.getWidth(),h=img1.getHeight(); 38 int[] pix = new int[w * h] 39 img1.getPixels(pix, 0, w, 0, 0, w, h); 40 int[] resultInt=LibImgFun.ImgFun(pix, w, h); 41 Bitmap resultImg=Bitmap.createBitmap(w, h, Config.RGB_565); 42 resultImg.setPixels(resultInt, 0, w, 0, 0,w, h); 43 long performance=System.currentTimeMillis()-current 44 imgView.setImageBitmap(resultImg); 45 HaveImgFun.this.setTitle(“w:”+String.valueOf(img1.getWidth())+“,h:”+String.valueOf(img1.getHeight())+“NDK耗时”+String.valueOf(performance)+“ 毫秒”); 46 } else if(v == btnRestore){ 47 Bitmap img2=((BitmapDrawable) getResources()。getDrawable(R.drawable.lena))。getBitmap(); 48 imgView.setImageBitmap(img2); 49 HaveImgFun.this.setTitle(“使用OpenCV进行图像处理”);50 } 51 }52} 53 }
点击全部保存,OK,现在可以选择一个Android虚拟机运行看一下效果,配置好Run Configuration然后点击Run,得到下面的结果:
点击使用C++ OpenCV进行处理,得到下面的结果:
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)