├── README.md
├── image
├── dill.fun.png
└── 在线验证图.png
├── pom.xml
└── src
└── main
├── java
├── com
│ └── cooooode
│ │ └── java12306
│ │ ├── service
│ │ └── VerifyService.java
│ │ └── util
│ │ ├── ImageProcessor.java
│ │ └── LabelImage.java
└── org
│ └── tensorflow
│ └── NativeLibrary.java
└── resources
└── model
├── label.txt
├── lenet-top.pb
└── mobilenet-pic.pb
/README.md:
--------------------------------------------------------------------------------
1 | # Java12306
2 | Java调用tensorflow pb模型进行图像分类做验证码识别,其它基本图像处理由java完成
3 |
4 | 模型.pb文件
5 | =
6 | 模型文件已上传可以直接clone
7 |
8 | - 字符分类使用lenet(src/main/resource/model/lennt-top.pb)
9 |
10 | - 图片分类使用mobilenet(src/main/resource/model/mobilenet-pic.pb)
11 |
12 | maven依赖
13 | =
14 | ```
15 |
16 |
36 |
37 |
The Java TensorFlow bindings require a native (JNI) library. This library 24 | * (libtensorflow_jni.so on Linux, libtensorflow_jni.dylib on OS X, tensorflow_jni.dll on Windows) 25 | * can be made available to the JVM using the java.library.path System property (e.g., using 26 | * -Djava.library.path command-line argument). However, doing so requires an additional step of 27 | * configuration. 28 | * 29 | *
Alternatively, the native libraries can be packaed in a .jar, making them easily usable from 30 | * build systems like Maven. However, in such cases, the native library has to be extracted from the 31 | * .jar archive. 32 | * 33 | *
NativeLibrary.load() takes care of this. First looking for the library in java.library.path 34 | * and failing that, it tries to find the OS and architecture specific version of the library in the 35 | * set of ClassLoader resources (under org/tensorflow/native/OS-ARCH). The resources paths used for 36 | * lookup must be consistent with any packaging (such as on Maven Central) of the TensorFlow Java 37 | * native libraries. 38 | */ 39 | final class NativeLibrary { 40 | private static final boolean DEBUG = 41 | System.getProperty("org.tensorflow.NativeLibrary.DEBUG") != null; 42 | private static final String JNI_LIBNAME = "tensorflow_jni"; 43 | 44 | public static void load() { 45 | if (isLoaded() || tryLoadLibrary()) { 46 | // Either: 47 | // (1) The native library has already been statically loaded, OR 48 | // (2) The required native code has been statically linked (through a custom launcher), OR 49 | // (3) The native code is part of another library (such as an application-level library) 50 | // that has already been loaded. For example, tensorflow/examples/android and 51 | // tensorflow/tools/android/inference_interface include the required native code in 52 | // differently named libraries. 53 | // 54 | // Doesn't matter how, but it seems the native code is loaded, so nothing else to do. 55 | return; 56 | } 57 | // Native code is not present, perhaps it has been packaged into the .jar file containing this. 58 | // Extract the JNI library itself 59 | final String jniLibName = System.mapLibraryName(JNI_LIBNAME); 60 | final String jniResourceName = makeResourceName(jniLibName); 61 | log("jniResourceName: " + jniResourceName); 62 | final InputStream jniResource = 63 | NativeLibrary.class.getClassLoader().getResourceAsStream(jniResourceName); 64 | // Extract the JNI's dependency 65 | final String frameworkLibName = 66 | getVersionedLibraryName(System.mapLibraryName("tensorflow_framework")); 67 | final String frameworkResourceName = makeResourceName(frameworkLibName); 68 | log("frameworkResourceName: " + frameworkResourceName); 69 | final InputStream frameworkResource = 70 | NativeLibrary.class.getClassLoader().getResourceAsStream(frameworkResourceName); 71 | // Do not complain if the framework resource wasn't found. This may just mean that we're 72 | // building with --config=monolithic (in which case it's not needed and not included). 73 | if (jniResource == null) { 74 | throw new UnsatisfiedLinkError( 75 | String.format( 76 | "Cannot find TensorFlow native library for OS: %s, architecture: %s. See " 77 | + "https://github.com/tensorflow/tensorflow/tree/master/tensorflow/java/README.md" 78 | + " for possible solutions (such as building the library from source). Additional" 79 | + " information on attempts to find the native library can be obtained by adding" 80 | + " org.tensorflow.NativeLibrary.DEBUG=1 to the system properties of the JVM.", 81 | os(), architecture())); 82 | } 83 | try { 84 | // Create a temporary directory for the extracted resource and its dependencies. 85 | final File tempPath = createTemporaryDirectory(); 86 | // Deletions are in the reverse order of requests, so we need to request that the directory be 87 | // deleted first, so that it is empty when the request is fulfilled. 88 | tempPath.deleteOnExit(); 89 | final String tempDirectory = tempPath.getCanonicalPath(); 90 | if (frameworkResource != null) { 91 | extractResource(frameworkResource, frameworkLibName, tempDirectory); 92 | } else { 93 | log( 94 | frameworkResourceName 95 | + " not found. This is fine assuming " 96 | + jniResourceName 97 | + " is not built to depend on it."); 98 | } 99 | System.load(extractResource(jniResource, jniLibName, tempDirectory)); 100 | } catch (IOException e) { 101 | throw new UnsatisfiedLinkError( 102 | String.format( 103 | "Unable to extract native library into a temporary file (%s)", e.toString())); 104 | } 105 | } 106 | 107 | private static boolean tryLoadLibrary() { 108 | try { 109 | System.loadLibrary(JNI_LIBNAME); 110 | return true; 111 | } catch (UnsatisfiedLinkError e) { 112 | log("tryLoadLibraryFailed: " + e.getMessage()); 113 | return false; 114 | } 115 | } 116 | 117 | private static boolean isLoaded() { 118 | try { 119 | TensorFlow.version(); 120 | log("isLoaded: true"); 121 | return true; 122 | } catch (UnsatisfiedLinkError e) { 123 | return false; 124 | } 125 | } 126 | 127 | private static boolean resourceExists(String baseName) { 128 | return NativeLibrary.class.getClassLoader().getResource(makeResourceName(baseName)) != null; 129 | } 130 | 131 | private static String getVersionedLibraryName(String libFilename) { 132 | final String versionName = getMajorVersionNumber(); 133 | 134 | // If we're on darwin, the versioned libraries look like blah.1.dylib. 135 | final String darwinSuffix = ".dylib"; 136 | if (libFilename.endsWith(darwinSuffix)) { 137 | final String prefix = libFilename.substring(0, libFilename.length() - darwinSuffix.length()); 138 | if (versionName != null) { 139 | final String darwinVersionedLibrary = prefix + "." + versionName + darwinSuffix; 140 | if (resourceExists(darwinVersionedLibrary)) { 141 | return darwinVersionedLibrary; 142 | } 143 | } else { 144 | // If we're here, we're on darwin, but we couldn't figure out the major version number. We 145 | // already tried the library name without any changes, but let's do one final try for the 146 | // library with a .so suffix. 147 | final String darwinSoName = prefix + ".so"; 148 | if (resourceExists(darwinSoName)) { 149 | return darwinSoName; 150 | } 151 | } 152 | } else if (libFilename.endsWith(".so")) { 153 | // Libraries ending in ".so" are versioned like "libfoo.so.1", so try that. 154 | final String versionedSoName = libFilename + "." + versionName; 155 | if (versionName != null && resourceExists(versionedSoName)) { 156 | return versionedSoName; 157 | } 158 | } 159 | 160 | // Otherwise, we've got no idea. 161 | return libFilename; 162 | } 163 | 164 | /** 165 | * Returns the major version number of this TensorFlow Java API, or {@code null} if it cannot be 166 | * determined. 167 | */ 168 | private static String getMajorVersionNumber() { 169 | String version = NativeLibrary.class.getPackage().getImplementationVersion(); 170 | // expecting a string like 1.14.0, we want to get the first '1'. 171 | int dotIndex; 172 | if (version == null || (dotIndex = version.indexOf('.')) == -1) { 173 | return "1"; 174 | } 175 | String majorVersion = version.substring(0, dotIndex); 176 | try { 177 | Integer.parseInt(majorVersion); 178 | return majorVersion; 179 | } catch (NumberFormatException unused) { 180 | return null; 181 | } 182 | } 183 | 184 | private static String extractResource( 185 | InputStream resource, String resourceName, String extractToDirectory) throws IOException { 186 | final File dst = new File(extractToDirectory, resourceName); 187 | dst.deleteOnExit(); 188 | final String dstPath = dst.toString(); 189 | log("extracting native library to: " + dstPath); 190 | final long nbytes = copy(resource, dst); 191 | log(String.format("copied %d bytes to %s", nbytes, dstPath)); 192 | return dstPath; 193 | } 194 | 195 | private static String os() { 196 | final String p = System.getProperty("os.name").toLowerCase(); 197 | if (p.contains("linux")) { 198 | return "linux"; 199 | } else if (p.contains("os x") || p.contains("darwin")) { 200 | return "darwin"; 201 | } else if (p.contains("windows")) { 202 | return "windows"; 203 | } else { 204 | return p.replaceAll("\\s", ""); 205 | } 206 | } 207 | 208 | private static String architecture() { 209 | final String arch = System.getProperty("os.arch").toLowerCase(); 210 | return (arch.equals("amd64")) ? "x86_64" : arch; 211 | } 212 | 213 | private static void log(String msg) { 214 | if (DEBUG) { 215 | System.err.println("org.tensorflow.NativeLibrary: " + msg); 216 | } 217 | } 218 | 219 | private static String makeResourceName(String baseName) { 220 | return "org/tensorflow/native/" + String.format("%s-%s/", os(), architecture()) + baseName; 221 | } 222 | 223 | private static long copy(InputStream src, File dstFile) throws IOException { 224 | FileOutputStream dst = new FileOutputStream(dstFile); 225 | try { 226 | byte[] buffer = new byte[1 << 20]; // 1MB 227 | long ret = 0; 228 | int n = 0; 229 | while ((n = src.read(buffer)) >= 0) { 230 | dst.write(buffer, 0, n); 231 | ret += n; 232 | } 233 | return ret; 234 | } finally { 235 | dst.close(); 236 | src.close(); 237 | } 238 | } 239 | 240 | // Shamelessly adapted from Guava to avoid using java.nio, for Android API 241 | // compatibility. 242 | private static File createTemporaryDirectory() { 243 | File baseDirectory = new File(System.getProperty("java.io.tmpdir")); 244 | String directoryName = "tensorflow_native_libraries-" + System.currentTimeMillis() + "-"; 245 | for (int attempt = 0; attempt < 1000; attempt++) { 246 | File temporaryDirectory = new File(baseDirectory, directoryName + attempt); 247 | if (temporaryDirectory.mkdir()) { 248 | return temporaryDirectory; 249 | } 250 | } 251 | throw new IllegalStateException( 252 | "Could not create a temporary directory (tried to make " 253 | + directoryName 254 | + "*) to extract TensorFlow native libraries."); 255 | } 256 | 257 | private NativeLibrary() {} 258 | } 259 | -------------------------------------------------------------------------------- /src/main/resources/model/label.txt: -------------------------------------------------------------------------------- 1 | 双面胶 2 | 红酒 3 | 珊瑚 4 | 鞭炮 5 | 安全帽 6 | 拖把 7 | 挂钟 8 | 沙拉 9 | 红豆 10 | 龙舟 11 | 电线 12 | 蚂蚁 13 | 红枣 14 | 海苔 15 | 文具盒 16 | 啤酒 17 | 苍蝇拍 18 | 耳塞 19 | 档案袋 20 | 雨靴 21 | 手掌印 22 | 菠萝 23 | 烛台 24 | 高压锅 25 | 樱桃 26 | 蜡烛 27 | 漏 斗 28 | 本子 29 | 蜥蜴 30 | 排风机 31 | 订书机 32 | 调色板 33 | 茶几 34 | 薯条 35 | 钟表 36 | 锣 37 | 盘子 38 | 海报 39 | 锅铲 40 | 冰箱 41 | 电子秤 42 | 毛线 43 | 辣椒酱 44 | 刺绣 45 | 创可贴 46 | 药片 47 | 老虎 48 | 茶盅 49 | 路灯 50 | 卷尺 51 | 剪纸 52 | 中国结 53 | 口哨 54 | 热水袋 55 | 话梅 56 | 牌坊 57 | 风铃 58 | 篮球 59 | 绿豆 60 | 护腕 61 | 开瓶器 62 | 铃铛 63 | 打字机 64 | 网球拍 65 | 日历 66 | 公交卡 67 | 海鸥 68 | 沙包 69 | 印章 70 | 电饭煲 71 | 狮子 72 | 蜜蜂 73 | 黑板 74 | 跑步机 75 | 金字塔 76 | 仪表盘 77 | 蒸笼 78 | 棉棒 79 | 航母 80 | 锦旗 -------------------------------------------------------------------------------- /src/main/resources/model/lenet-top.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vua/Java12306/2f8cd9fc8fbc0d8174e01d54c7bb51b18e6d597f/src/main/resources/model/lenet-top.pb -------------------------------------------------------------------------------- /src/main/resources/model/mobilenet-pic.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vua/Java12306/2f8cd9fc8fbc0d8174e01d54c7bb51b18e6d597f/src/main/resources/model/mobilenet-pic.pb --------------------------------------------------------------------------------