JNA调用Caffe生成的OCR 服务端

服务端代码:

import com.sun.jna.Library;

import com.sun.jna.Native;

import java.io.*;

import java.net.InetAddress;

import java.net.ServerSocket;

import java.net.Socket;


public class OcrServer {

    //全局是否运行中的标志位

    private static ServerSocket server = null;

    //TODO 修改监听端口

    private static int iOcrPort = 4444;

    private static String sOcrFolderName = "ocrLib";

    private static String sHomePath = System.getProperty("user.dir");

    private static String sDllPath = sHomePath+"\\"+ sOcrFolderName +"\\Ocr.dll";

    //主程序

    public static void main(String[] args) {

        MyRunnable mi = new MyRunnable();

        Thread t = new Thread(mi);

        t.start();

    }

    //线程函数

    static class MyRunnable implements Runnable {

        @Override

     public void run() {

            startServer();

     }

    }

    //CPU模式识别

    private static void startServer() {

        System.out.println("当前目录:"+sHomePath);

        System.out.println("识别库目录:"+sHomePath+"\\"+ sOcrFolderName +"\\");

        System.out.println("识别库DLL:"+sHomePath+"\\"+ sOcrFolderName +"\\Ocr.dll");

        System.out.println("识别库初始化中......");

        

        // 初始化识别库

        //TODO 修改这里, 变更识别模式

        // 第二个参数如果是CPU模式, 传-1, 如果是GPU模式, 传 GPU序号, 1块显卡传0, 2块显卡可以选0和1

        OCRDll.INSTANCE.INIT(sHomePath +"\\"+ sOcrFolderName +"\\", -1, 1);

        //图片数据放在这里

        byte[] bData;

        System.out.println("识别库初始化完成!");

        System.out.println("正在启动服务器......");

        

        InputStreamReader isr;

        BufferedReader br;

        OutputStreamWriter osw;

        BufferedWriter bw;

        String str, sFile;

        try {

                // 在本机的4444端口开放Server

                server = new ServerSocket(iOcrPort);

            System.out.println("服务器已启动, 监听端口: "+Integer.toString(iOcrPort));

            CLibrary.INSTANCE.MessageBoxTimeoutA(0, "服务器已启动, 监听端口: "+Integer.toString(iOcrPort), "提示", 64, 0, 3000);

            //不能开启超时, 开启后, 一段时间内没有客户端连接, 服务器就会退出.

            //server.setSoTimeout(30000);

            while (true) {

                //只要产生连接,socket便可以代表所连接的那个物体,同时这个server.accept()只有产生了连接才会进行下一步操作。

                Socket socket = server.accept();

                InetAddress clientIp = socket.getInetAddress();

                System.out.println("建立了一个连接!" + clientIp.toString());

                //取得输入流

                isr = new InputStreamReader(socket.getInputStream(), "GBK");

                br = new BufferedReader(isr);

                clientIp = socket.getInetAddress();

                sFile = br.readLine();

                if(sFile != null){

                    System.out.println(clientIp.toString() + ":" + sFile.length());

                    //取得输出流对象

                    osw = new OutputStreamWriter(socket.getOutputStream(), "GBK");

                    bw = new BufferedWriter(osw);

                    //删除十六进制开头的0x符

                    sFile = sFile.substring(2,sFile.length());

                    //把读取到的十六进制文本, 转成字节数组

                    bData = hexstring2byte(sFile);

                    //如果转成功了. 则去识别

                    if(bData.length > 0){

                        //System.out.println("图片长度:"+bData.length);

                        str = doOcr(bData);

                        System.out.println("图片长度:"+bData.length +", 识别结果:" + str);

                        bw.write(str+"\n");

                    }

                    bw.flush();

                    bw.close();

                    osw.close();

                }

                br.close();

                isr.close();

                socket.close();

            }

        } catch (IOException e) {

            e.printStackTrace();

            System.out.println("服务器启动失败,请检查端口是否被占用!");

            CLibrary.INSTANCE.MessageBoxTimeoutA(0, "服务器启动失败,请检查端口是否被占用!", "警告", 48, 0, 3000);

        }

    }

    //系统MessageBoxTimeoutA API

    public interface CLibrary extends Library {

CLibrary INSTANCE = (CLibrary) Native.loadLibrary("User32", CLibrary.class);

//int MessageBoxTimeoutA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId, DWORD dwMilliseconds);

int MessageBoxTimeoutA(int hwnd, String sText, String sTitle, int uType, int wLanguageID, int dwMillisecondsi);

}

    // OCR dll 调用接口

    public interface OCRDll extends Library {

        OCRDll INSTANCE = Native.loadLibrary(sDllPath, OCRDll.class);

        void INIT(String rpcPath, int gpuID, int ii);

        int OCR(byte[] read, int iLen, byte[] ret);

    }

    //真正的识别函数. 调用机器学习生成的DLL库, 识别图片

    private static String doOcr(byte[] read) {

        // 存储结果的缓冲区

        byte[] bRet = new byte[512];

        // 调用识别

        OCRDll.INSTANCE.OCR(read, read.length, bRet);

        // 存储结果字符串

        String sRet = "";

        // 从结果缓冲区中取出结果

        for (byte aBRet : bRet) {

            if (aBRet != 0)

                sRet += (char) aBRet;

            else

                break;

        }

        //System.out.println("识别结果:" + sRet);

        return sRet;

    }

    //16进制字符串到字节数组

    private static byte[] hexstring2byte(String s) {

     int len = s.length();

     byte[] b = new byte[len / 2];

     for (int i = 0; i < len; i += 2) {

     // 两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个字节

     b[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character

     .digit(s.charAt(i + 1), 16));

     }

     return b;

    }

}

客户端代码:

public static String ocr(BufferedImage imgPintu, String sIp, int sPort) {
    String sRet = "";
    try {
        //连接服务端
        Socket socket = new Socket();
        //设置超时时间30秒
        socket.connect(new InetSocketAddress(sIp, sPort), 30000);
        //获取连接的IP
        //InetAddress ipAddress = socket.getInetAddress();
        // 输出连接者的IP。
        //System.out.println(ipAddress.toString()+"成功连接服务器");
        //获取输出流
        OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream(), "GBK");
        BufferedWriter bw = new BufferedWriter(osw);
        //通过数据流转字节数组
        ByteArrayOutputStream out = new ByteArrayOutputStream();  	            
        ImageIO.write(imgPintu, "png", out);
        byte[] bImg= out.toByteArray();
        //字节数组转16进制文本
        String sImg = ManagePhoto.byte2hexstring(bImg);
        System.out.println("图片长度 = "+bImg.length +"\r\n十六进制长度 = "+sImg.length());
        //将内容写到输出流, 发送到服务器
        bw.write(sImg+"\n");
        bw.flush();
        //取得输入流对象
        InputStreamReader isr = new InputStreamReader(socket.getInputStream(), "GBK");
        BufferedReader br = new BufferedReader(isr);
        //读取结果
        sRet = br.readLine();
        
        //关闭连接
        br.close();
        isr.close();
        bw.close();
        osw.close();
        socket.close();
    } catch (Exception e) {
        System.err.println("Error: Connect server failed!!");
    }
    //如果返回结果长度大于10, 证明是正确的
    if (sRet != null && sRet.length() > 10)
        sRet = sRet.substring(0, sRet.length() - 1);
    //System.out.println( "识别结果  = " +sRet );
    return sRet;
}

// byte数组到16进制字符串
public static String byte2hexstring(byte[] data) {
    if (data == null || data.length <= 1)
        return "0x";
    StringBuffer sb = new StringBuffer();
    int buf[] = new int[data.length];
    for (int k = 0; k < data.length; k++) {
        buf[k] = data[k] < 0 ? (data[k] + 256) : (data[k]);
    }
    for (int k = 0; k < buf.length; k++) {
        if (buf[k] < 16)
            sb.append("0" + Integer.toHexString(buf[k]));
        else
            sb.append(Integer.toHexString(buf[k]));
    }
    return "0x" + sb.toString().toUpperCase();
}

 

你可能感兴趣的:(JNA调用Caffe生成的OCR 服务端)