0x00 基本环境
需要添加以下依赖的Jar包
0x01 JwxtCaptchaCrack.java
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import net.coobird.thumbnailator.Thumbnails;
import org.tensorflow.framework.DataType;
import org.tensorflow.framework.TensorProto;
import org.tensorflow.framework.TensorShapeProto;
import tensorflow.serving.Model;
import tensorflow.serving.Predict;
import tensorflow.serving.PredictionServiceGrpc;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class JwxtCaptchaCrack {
String host;
int port;
public JwxtCaptchaCrack(String host, int port){
this.host = host;
this.port = port;
}
/**
* 教务系统验证码所在的路径
* */
public String crackCaptcha(String file) throws IOException {
//#记个时
long t = System.currentTimeMillis();
// String file = "D:\\\\jwxt\\\\new_test\\\\4am7.jpg";
//读取文件,强制修改图片大小,设置输出文件格式bmp(模型定义时输入数据是无编码的)
BufferedImage im = Thumbnails.of(file).forceSize(180, 60).outputFormat("bmp").asBufferedImage();
//转换图片到图片数组,匹配输入数据类型为Float
Raster raster = im.getData();
List<Float> floatList = new ArrayList<>();
float [] temp = new float[raster.getWidth() * raster.getHeight() * raster.getNumBands()];
float [] pixels = raster.getPixels(0,0,raster.getWidth(),raster.getHeight(),temp);
float []img = new float[pixels.length / 3];
//在图片处理的同时顺便
for (int i = 0 ; i < pixels.length / 3 ; i++){
floatList.add((pixels[i*3] + pixels[i*3+1] + pixels[i*3+2])/(3*255));
}
// System.out.println("time cost:" + (System.currentTimeMillis() - t));
//#创建连接,注意usePlaintext设置为true表示用非SSL连接
ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext(true).build();
//这里还是先用block模式
PredictionServiceGrpc.PredictionServiceBlockingStub stub = PredictionServiceGrpc.newBlockingStub(channel);
//创建请求
Predict.PredictRequest.Builder predictRequestBuilder = Predict.PredictRequest.newBuilder();
//模型名称和模型方法名预设
Model.ModelSpec.Builder modelSpecBuilder = Model.ModelSpec.newBuilder();
modelSpecBuilder.setName("crack_captcha");
modelSpecBuilder.setSignatureName("serving_default");
predictRequestBuilder.setModelSpec(modelSpecBuilder);
//设置入参,访问默认是最新版本,如果需要特定版本可以使用tensorProtoBuilder.setVersionNumber方法
TensorProto.Builder tensorProtoBuilder = TensorProto.newBuilder();
tensorProtoBuilder.setDtype(DataType.DT_FLOAT);
TensorShapeProto.Builder tensorShapeBuilder = TensorShapeProto.newBuilder();
tensorShapeBuilder.addDim(TensorShapeProto.Dim.newBuilder().setSize(1));
tensorShapeBuilder.addDim(TensorShapeProto.Dim.newBuilder().setSize(60*180));
tensorProtoBuilder.setTensorShape(tensorShapeBuilder.build());
tensorProtoBuilder.addAllFloatVal(floatList);
predictRequestBuilder.putInputs("image", tensorProtoBuilder.build());
//访问并获取结果
Predict.PredictResponse predictResponse = stub.predict(predictRequestBuilder.build());
String tmp = "";
for (int i = 0 ;i < 4 ; i ++){
long l = predictResponse.getOutputsOrThrow("out").getInt64Val(i);
if (l < 10){
tmp += (char)(l+'0');
}else {
tmp += (char)(l-10 + 'a');
}
}
// System.out.println("cost time: " + (System.currentTimeMillis() - t));
return tmp;
}
}
0x02 Main.java
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
//部署的tensorflow-serving服务器的ip以及端口
JwxtCaptchaCrack jwxtCaptchaCrack = new JwxtCaptchaCrack("192.168.190.128",9000);
jwxtCaptchaCrack.crackCaptcha("D:\\jwxt\\new_test\\2bc2.jpg");
}
}
0x03 输出
0x04 总结
至此从训练集的收集到训练测试以及部署整个的流程都走完了。
题外话,博主也基于这个项目实现了自动识别学校教务系统的验证码然后查成绩的项目。
0x05 后记
在整个项目的开完以及之后的本系列的博文写作中,得到了很多人的帮助与支持。在此向他们表示由衷的的感谢。
特别是
####不愿透露姓名的YY同学提供的带GPU的设备支持。