From 5361c3cdf5d780fd7e534008ce8811c749f23fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=96=87=E6=96=87?= Date: Thu, 15 Oct 2020 16:26:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=B4=E6=98=8E=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 88 ++++++----------- README_EN.md | 98 +++++++------------ app/build.gradle | 3 + .../main/java/com/zww/sample/MainActivity.kt | 1 - build.gradle | 4 - nsfw/build.gradle | 8 +- nsfw/src/main/java/com/zwy/nsfw/NSFWHelper.kt | 18 +++- nsfw_initializer/build.gradle | 10 +- 8 files changed, 93 insertions(+), 137 deletions(-) diff --git a/README.md b/README.md index 2fe6026a..2cc01030 100644 --- a/README.md +++ b/README.md @@ -13,86 +13,58 @@ ### JavaScript参考[JS相关文档](https://js.tensorflow.org/api/latest/) >>> 其中Python、C++均有两种数据喂入的方式,可根据需求选择pb模型或tfLite文件,详细请参考上面的链接.Java的目前只能加载pb模型。其他的平台可自行[百度](https://www.baidu.com) ### 本项目移除测试图片,请下载Demo后自行配图测试 -#### Demo使用MVVM模式,可用作开发脚手架使用 -`Kotlin+okhttp3+rxjava2+retrofit2+koin+glide+greendao+databinding+Livedata` - -![MVVM](https://github.com/devzwy/open_nsfw_android/blob/dev/img/4.jpg) +#### 测试图片 -#### 1.3.5版本优化说明: -模型大小改动较大,原量化模型虽小(6M),但对GPU加速支持不友好,新模型大约23M,完美支持GPU加速并优化识别精度,加速效果明显。建议全部升级该版本。__新版本的GPU加速默认开启状态__,SDK默认会检测设备是否支持,不支持时会自动取消加速(老版本会奔溃) -#### 1.3.4版本特殊说明: -由于模型支持GPU加速后模型文件变大,部分用户反馈Apk体积增大,考虑到这方面,在1.3.4版本中增加初始化方式,可通过传入模型文件的路径进行初始化,该模型在`/OpenNSFW/src/main/assets/nsfw.tflite`处,可自行下载并存放适当位置,比如放在后台,app端自行下载后初始化NSFW后使用。初始化方式: -``` - Classifier.Build() -// .context(this) //1.3.4版本可不用调用该代码。其他版本必须调用,否则会有异常抛出 -// .isOpenGPU(true)//GPU加速 -// .numThreads(100) //分配的线程数 根据手机配置设置,默认1 - .nsfwModuleFilePath("/data/user/0/com.zwy.demo/files/nsfw.tflite") //1.3.4版本必须配置模型存放路径,否则会有异常抛出 - .build() -``` - ### 开始使用 -- 添加远程仓库支持 -``` - allprojects { - repositories { - maven { url 'https://jitpack.io' } - } - } -``` - -- 配置依赖(如果需要自行配置模型路径可适用1.3.4版本,否则请使用最新版本,版本号看右边的icon中的数字) [![](https://jitpack.io/v/devzwy/open_nsfw_android.svg)](https://jitpack.io/#devzwy/open_nsfw_android) (编译过程报错时请自行使用梯子) -``` - dependencies { - //versionCode:上面小icon中最新版本号 - implementation 'com.github.devzwy:open_nsfw_android:[versionCode]' - } - -``` +- 开启tflite文件支持 -- 以下配置1.3.4版本可跳过 -__除1.3.4版本外,其他任何版本均需要添加如下代码,否则会有`java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed`异常抛出,因为assets下模型文件较大__ ``` android { aaptOptions { noCompress "tflite" } } -``` +``` +- 引入依赖 +``` + //可选 快速初始化扫描器,可免去初始化代码 + implementation 'com.zwy.nsfw:nsfw_initializer:1.3.7' + //必须 扫描器核心文件 + implementation 'com.zwy.nsfw:nsfw:1.3.7' +``` -- 建议在Application中全局初始化 +- 初始化 ``` - Classifier.Build() - .context(this) //1.3.4版本可不用调用该代码。其他版本必须调用,否则会有异常抛出 -// .isOpenGPU(true)//GPU加速 -// .numThreads(100) //分配的线程数 根据手机配置设置,默认1 -// .nsfwModuleFilePath("/data/user/0/com.zwy.demo/files/nsfw.tflite") //1.3.4版本必须配置模型存放路径,否则会有异常抛出 - .build() + //方式一,将模型文件放在Assets根目录下并命名为nsfw.tflite + NSFWHelper.init(context = this@Application) + + //方式二,适用于产品对apk大小控制严格,无法将模型文件直接放在apk中,可在用户打开Apk后台静默下载后指定模型路径进行初始化 + NSFWHelper.init(modelPath = "模型文件存放路径") + + //方式三,将模型文件放在Assets根目录下并命名为nsfw.tflite,引用该库可免去初始化代码 + implementation 'com.zwy.nsfw:nsfw_initializer:1.3.7' + ``` - 使用: -``` - //方式一: - val nsfwBean = Classifier.Build().context(this).build().run(bitmap) - //方式二 - val nsfwBean = bitmap.getNsfwScore() - //方式三 - val nsfwBean = file.getNsfwScore() - - nsfwBean.sfw ... 非涉黄数值 数值越大约安全 - nsfwBean.nsfw ... 涉黄数值 数值越大约危险 ``` + //val mNSFWScoreBean:NSFWScoreBean = File.getNSFWScore() + //val mNSFWScoreBean:NSFWScoreBean = Bitmap.getNSFWScore() + //val mNSFWScoreBean:NSFWScoreBean = NSFWHelper.getNSFWScore(bitmap) + + mNSFWScoreBean.sfw ... 非涉黄数值 数值越大约安全 + mNSFWScoreBean.nsfw ... 涉黄数值 数值越大约危险 + mNSFWScoreBean.timeConsumingToLoadData ... 装载数据耗时 单位ms + mNSFWScoreBean.timeConsumingToScanData ... 扫描图片耗时 单位ms +``` + ### 安卓手机直接[点我安装](http://d.6short.com/q9cv) ### 扫码下载 ![图片](https://github.com/devzwy/open_nsfw_android/blob/dev/img/2.png) - -### Demo运行结果: - -![图片](https://github.com/devzwy/open_nsfw_android/blob/dev/img/1.png) diff --git a/README_EN.md b/README_EN.md index d51f5119..932b84fa 100644 --- a/README_EN.md +++ b/README_EN.md @@ -13,86 +13,58 @@ ### JavaScript like this[js doc](https://js.tensorflow.org/api/latest/) >>> Python and C + + have two ways to feed data. You can select PB model or tflite file according to your needs. Please refer to the above link for details. Java can only load PB model at present. Other platforms can [Google]( https://www.google.cn ) ### This project removes the test picture, please download demo and test by yourself -#### Demo uses MVVM mode, which can be used to develop scaffolding -`Kotlin+okhttp3+rxjava2+retrofit2+koin+glide+greendao+databinding+Livedata` - -![MVVM](https://github.com/devzwy/open_nsfw_android/blob/dev/img/4.jpg) +#### picture -#### 1.3.5 optimization description: -Although the original quantization model is small (6m), it is not friendly to GPU acceleration. The new model is about 23m, which perfectly supports GPU acceleration and optimizes the recognition accuracy. The acceleration effect is obvious. It is recommended to upgrade all of this version__ The new version of GPU acceleration is on by default__ By default, the SDK will detect whether the device supports it. If it does not, it will automatically cancel the acceleration (the old version will crash) -#### 1.3.4 Special description of this version: -Since the model supports GPU acceleration, the model file becomes larger, and some users feedback that the APK volume increases. In this regard, the initialization method is added in version 1.3.4, which can be initialized through the path of the model file. The model can be initialized in '/ opennsfw / SRC / main / assets/ nsfw.tflite `You can download and store it in an appropriate location by yourself, such as in the background, and the app will download it by itself Use after nsfw. Initialization mode: -``` - Classifier.Build() -// .context(this) //Version 1.3.4 does not need to call this code. Other versions must be called, otherwise an exception will be thrown -// .isOpenGPU(true)//GPU acceleration -// .numThreads(100) //The number of threads allocated is set according to the phone configuration. The default value is 1 - .nsfwModuleFilePath("/data/user/0/com.zwy.demo/files/nsfw.tflite") //Version 1.3.4 must configure the model storage path, otherwise an exception will be thrown - .build() -``` +### start use -### dependencies -- add jitpack repository -``` - allprojects { - repositories { - maven { url 'https://jitpack.io' } - } - } -``` - -- Configuration dependency (if you need to configure the model path by yourself, version 1.3.4 is applicable; otherwise, please use the latest version. For version number, see the number in the icon on the right) [![](https://jitpack.io/v/devzwy/open_nsfw_android.svg)](https://jitpack.io/#devzwy/open_nsfw_android) +- Open tflite support -``` - dependencies { - //versionCode:The latest version number in the small icon above - implementation 'com.github.devzwy:open_nsfw_android:[versionCode]' - } - -``` - -- The following configuration version 1.3.4 can be skipped -__Except for version 1.3.4, the following code needs to be added to any other version, otherwise there will be`java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed`Exception thrown, because the model file under assets is large__ ``` android { aaptOptions { noCompress "tflite" } } -``` +``` +- Dependencies +``` + //Optional Quick initialization of scanner, can avoid initialization code + implementation 'com.zwy.nsfw:nsfw_initializer:1.3.7' + //must Scanner core file + implementation 'com.zwy.nsfw:nsfw:1.3.7' +``` -- Global initialization in application +- Initialization ``` - Classifier.Build() - .context(this) //Version 1.3.4 does not need to call this code. Other versions must be called, otherwise an exception will be thrown -// .isOpenGPU(true)//GPU acceleration -// .numThreads(100) //The number of threads allocated is set according to the phone configuration. The default value is 1 -// .nsfwModuleFilePath("/data/user/0/com.zwy.demo/files/nsfw.tflite") //Version 1.3.4 must configure the model storage path, otherwise an exception will be thrown - .build() -``` -- use: - -``` - //like this: - val nsfwBean = Classifier.Build().context(this).build().run(bitmap) - //or like this - val nsfwBean = bitmap.getNsfwScore() - //or like this - val nsfwBean = file.getNsfwScore() - - nsfwBean.sfw ... The more approximate the value, the safer it is - nsfwBean.nsfw ... The more approximate the value, the more dangerous it is + //Method 1: put the model file in the assets root directory and name it nsfw.tflite + NSFWHelper.init(context = this@Application) + + //Method 2 is applicable to the product that strictly controls the size of the APK and cannot directly put the model file in the APK. It can be initialized by specifying the model path after the user opens the APK background and downloads it silently + NSFWHelper.init(modelPath = "modelPath") + + //Method 3: put the model file in the assets root directory and name it nsfw.tflite To refer to the library can avoid initializing the code + implementation 'com.zwy.nsfw:nsfw_initializer:1.3.7' + ``` -### android install[click me to installing](http://d.6short.com/q9cv) +- GetNSFWScore: -### Scan qrcode to download +``` + //val mNSFWScoreBean:NSFWScoreBean = File.getNSFWScore() + //val mNSFWScoreBean:NSFWScoreBean = Bitmap.getNSFWScore() + //val mNSFWScoreBean:NSFWScoreBean = NSFWHelper.getNSFWScore(bitmap) + + mNSFWScoreBean.sfw ... The more approximate the non yellow value is, the safer it is + mNSFWScoreBean.nsfw ... The more the Yellow value is, the more dangerous it will be + mNSFWScoreBean.timeConsumingToLoadData ... Load data in milliseconds + mNSFWScoreBean.timeConsumingToScanData ... Scan picture in milliseconds +``` -![pic](https://github.com/devzwy/open_nsfw_android/blob/dev/img/2.png) +### Android mobile phone direct[Click me to install](http://d.6short.com/q9cv) -### Demo run results: +### Scan code to download -![pic2](https://github.com/devzwy/open_nsfw_android/blob/dev/img/1.png) +![pic](https://github.com/devzwy/open_nsfw_android/blob/dev/img/2.png) \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index f35712fb..3c7427c3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -46,4 +46,7 @@ dependencies { //权限 implementation 'com.yanzhenjie:permission:2.0.3' + +// implementation 'com.zwy.nsfw:nsfw_initializer:1.3.7' +// implementation 'com.zwy.nsfw:nsfw:1.3.7' } diff --git a/app/src/main/java/com/zww/sample/MainActivity.kt b/app/src/main/java/com/zww/sample/MainActivity.kt index e600c65e..9316cbfd 100644 --- a/app/src/main/java/com/zww/sample/MainActivity.kt +++ b/app/src/main/java/com/zww/sample/MainActivity.kt @@ -5,7 +5,6 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.zwy.nsfw.getNSFWScore import java.util.* - class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/build.gradle b/build.gradle index 8adc196b..f2ce3055 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,6 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:4.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'org.greenrobot:greendao-gradle-plugin:3.3.0' classpath "guru.stefma.bintrayrelease:bintrayrelease:1.0.0" } } @@ -18,9 +17,6 @@ allprojects { google() jcenter() mavenCentral() - maven { - url 'https://jitpack.io' - } } } diff --git a/nsfw/build.gradle b/nsfw/build.gradle index a7a2efb6..7d0f5f6b 100644 --- a/nsfw/build.gradle +++ b/nsfw/build.gradle @@ -9,8 +9,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 30 - versionCode 136 - versionName "1.3.6" + versionCode 137 + versionName "1.3.7" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -37,12 +37,12 @@ dependencies { implementation 'org.tensorflow:tensorflow-lite-gpu:2.1.0' } -version = "1.3.6" +version = "1.3.7" group = "com.zwy.nsfw" publish { userOrg = 'devzwy' repoName = 'maven' - artifactId = 'com.zwy.nsfw' + artifactId = 'nsfw' desc = 'android端离线鉴黄库' website = 'https://github.com/devzwy' } diff --git a/nsfw/src/main/java/com/zwy/nsfw/NSFWHelper.kt b/nsfw/src/main/java/com/zwy/nsfw/NSFWHelper.kt index f168fb8a..377751fb 100644 --- a/nsfw/src/main/java/com/zwy/nsfw/NSFWHelper.kt +++ b/nsfw/src/main/java/com/zwy/nsfw/NSFWHelper.kt @@ -34,11 +34,17 @@ object NSFWHelper { */ private val INPUT_HEIGHT = 224 + /** + * SDK是否初始化完成 + */ + private var isSDKInit = false + /** * 手动初始化时必须传入模型文件的路径否则会有异常抛出 * 自动初始化需要将模型存放在资源文件assets根目录下,且名称必须为:'nsfw.tflite',不可改动 */ - fun init(context: Context? = null, modelPath: String?) { + fun init(context: Context? = null, modelPath: String? = null) { + if (context == null && modelPath==null) throw RuntimeException("初始化失败,您必须选择一种初始化方式,初始化方式一:NSFWHelper.init(context = this@Application),初始化方式二:[implementation 'com.zwy.nsfw:nsfw_initializer:+'],初始化方式三:NSFWHelper.init(modelPath = \"模型文件存放路径\")。说明:方式一和方式二均需要手动将模型文件放在Assets根目录下,并命名为nsfw.tflite,方式三适用于产品对apk大小控制严格,无法将模型文件直接放在apk中,可在用户打开Apk后台静默下载后指定模型路径进行初始化,三种方式任选其一即可") if (modelPath != null && modelPath.isNotEmpty()) { log("手动初始化...") File(modelPath).let { modelFile -> @@ -65,9 +71,13 @@ object NSFWHelper { } imgData = ByteBuffer.allocateDirect(1 * INPUT_WIDTH * INPUT_HEIGHT * 3 * 4) imgData.order(ByteOrder.LITTLE_ENDIAN) + isSDKInit = true } - + // + //初始化方式一:NSFWHelper.init(context = this@Application),初始化方式二:[implementation 'com.zwy.nsfw:nsfw_initializer:+'],初始化方式三:NSFWHelper.init(modelPath = "模型文件存放路径")。说明:方式一和方式二均需要手动将模型文件放在Assets根目录下,并命名为nsfw.tflite,方式三适用于产品对apk大小控制严格,无法将模型文件直接放在apk中,可在用户打开Apk后台静默下载后指定模型路径进行初始化,三种方式任选其一即可 + // + // /** * 关闭日志输出 */ @@ -116,6 +126,10 @@ object NSFWHelper { // # 删除所有单维度的条目 // # 输出扫描结果 fun getNSFWScore(bitmap: Bitmap): NSFWScoreBean { + if (!isSDKInit) throw RuntimeException( + "SDK未初始化,请初始化后使用。方式一:如果您的模型文件存放在Assets下并名称必须为:nsfw.tflite,请直接引用[implementation 'com.zwy.nsfw:nsfw_initializer:1.3.7']可免去初始化过程(模型文件在demo中有存放)" + + "方式二:否则需要指定模型文件的路径,使用:'NSFWHelper.init(modelPath = \"模型文件的路径\")'进行初始化,两者任选其一即可(后者适用于如果模型置于Apk中导致Apk体积超出产品预算时,可将模型文件后台下载至用户手机中后指定路径进行手动初始化)" + ) SystemClock.uptimeMillis().let { startTime -> //缩放位图时是否应使用双线性过滤。如果这是正确的,则在缩放时将使用双线性滤波,从而以较差的性能为代价具有更好的图像质量。如果这是错误的,则使用最近邻居缩放,这将使图像质量较差但速度更快。推荐的默认设置是将滤镜设置为“ true”,因为双线性滤镜的成本通常很小,并且改善的图像质量非常重要 ByteArrayOutputStream().let { stream -> diff --git a/nsfw_initializer/build.gradle b/nsfw_initializer/build.gradle index f5cef5b9..d330ab5f 100644 --- a/nsfw_initializer/build.gradle +++ b/nsfw_initializer/build.gradle @@ -9,8 +9,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 30 - versionCode 136 - versionName "1.3.6" + versionCode 137 + versionName "1.3.7" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -36,12 +36,12 @@ dependencies { } -version = "1.3.6" -group = "com.zwy.nsfw_initializer" +version = "1.3.7" +group = "com.zwy.nsfw" publish { userOrg = 'devzwy' repoName = 'maven' - artifactId = 'com.zwy.nsfw_initializer' + artifactId = 'nsfw_initializer' desc = 'android端离线鉴黄库快速初始化库' website = 'https://github.com/devzwy' }