JavaWeb调用Python深度学习算法,通过Base64实现帧(OpenCV)图片传递。(详细讲解Python,SpringBoot,Vue三方交互)

2 篇文章 0 订阅
1 篇文章 0 订阅

前言

今天给大家分享的是SpringBoot利用Socket与Python深度学习算法进行通信,并将Python算法处理后的帧图片转化为Base64传给SpringBoot后端,最终在Vue前端显示的三方交互教程。

Python深度学习算法

我这里的算法(video.py)是利用摄像头检测人脸,标出先验框,然后返回标注好的视频帧,其他算法一样的思路。

#-------------------------------------#
#       调用摄像头检测
#-------------------------------------#
from retinaface import Retinaface
from PIL import Image
import numpy as np
import cv2
import time


def facetest():
    retinaface = Retinaface()
    # 调用摄像头
    capture=cv2.VideoCapture(0) # capture=cv2.VideoCapture("1.mp4")

    fps = 0.0

    t1 = time.time()
    # 读取某一帧
    ref,frame=capture.read()
    # 格式转变,BGRtoRGB
    frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)

    # 进行检测
    frame = np.array(retinaface.detect_image(frame))

    # RGBtoBGR满足opencv显示格式
    frame = cv2.cvtColor(frame,cv2.COLOR_RGB2BGR)

    fps  = ( fps + (1./(time.time()-t1)) ) / 2
    print("fps= %.2f"%(fps))
    #标注视频帧
    frame = cv2.putText(frame, "fps= %.2f"%(fps), (0,     40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
    capture.release()
    #返回标注好的视频帧,这里返回的是opencv的类型
    return frame

Python脚本

将python脚本写成进程为java提供服务,在java应用程序中调用python进程提供的服务。(这里提一下各种方式读入的图片都可以转成Base64,但是转化方式不同,个人觉得opencv最不容易,因为转换方式不对很可能会导致前端无法正常显示,因此在这里我就以opencv格式来讲解,当然读入图片的方式还有两种,一种是f.read()以二进制读入,很多博客都是以此为例,故不详细讲解。另一种是PIL读入的Image是包含在opencv转化内了。)

#导入深度学习算法
from video import facetest
import cv2
import socket
import threading
from PIL import Image
import base64
import json
from io import BytesIO


def main():
    # 创建服务器套接字
    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 获取本地主机名称
    host = socket.gethostname()
    # 设置一个端口
    port = 12345
    # 将套接字与本地主机和端口绑定
    serversocket.bind((host, port))
    # 设置监听最大连接数
    serversocket.listen(5)
    # 获取本地服务器的连接信息
    myaddr = serversocket.getsockname()
    print("服务器地址:%s" % str(myaddr))
    # 循环等待接受客户端信息
    while True:
        # 获取一个客户端连接
        clientsocket, addr = serversocket.accept()
        print("连接地址:%s" % str(addr))
        try:
            t = ServerThreading(clientsocket)  # 为每一个请求开启一个处理线程
            t.start()
            pass
        except Exception as identifier:
            print(identifier)
            pass
        pass
    serversocket.close()
    pass

class ServerThreading(threading.Thread):
    # words = text2vec.load_lexicon()
    def __init__(self, clientsocket, recvsize=1024 * 1024, encoding="utf-8"):
        threading.Thread.__init__(self)
        self._socket = clientsocket
        self._recvsize = recvsize
        self._encoding = encoding
        pass

    def run(self):
        print("开启线程.....")
        try:
            # 接受Springboot传来的指令数据
            msg = ''
            while True:
                # 读取recvsize个字节
                rec = self._socket.recv(self._recvsize)
                # 解码
                msg += rec.decode(self._encoding)
                # 文本接受是否完毕,因为python socket不能自己判断接收数据是否完毕,
                # 所以需要自定义协议标志数据接受完毕
                if msg.strip().endswith('over'):
                    break
            #调用检测算法,并接收算法返回的视频帧(opencv),将每一帧转化为Image
            #如果传回来的帧就是Image则无需转换,所以上面说包含于此
            img = Image.fromarray(cv2.cvtColor(facetest(), cv2.COLOR_BGR2RGB)) 
            #创建一个BytesIO()
            output_buffer = BytesIO() 
            #写入output_buffer
            img.save(output_buffer,format='JPEG') 
            #在内存中读取
            byte_data = output_buffer.getvalue() 
            #转化为base64
            sendmsg = base64.b64encode(byte_data) 
            #如果需要传回的数据较多可以构造一个Json
            #str(sendmsg)[2:-1]是为了去掉Base64的格式
            jsons = json.dumps({'base64code': str(sendmsg)[2:-1], 'name': 'wuwenjun'}, sort_keys=True, indent=4, separators=(',', ': '))
            # 像SpringBoot发送数据
            self._socket.send(("%s" % jsons).encode(self._encoding))
            pass
        except Exception as identifier:
            self._socket.send("500".encode(self._encoding))
            print(identifier)
            pass
        finally:
            self._socket.close()
        print("任务结束.....")

        pass

    def __del__(self):
        pass


if __name__ == "__main__":
    main()

在JavaWeb代码中访问python进程的代码

这里SpringBoot将接收来自Python算法返回的结果,可以是字符串,也可以是Base64的图片,当然也可以是既包含图片和字符串等的Json。

package com.example.wuwenjun.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.lang.System;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.InputStream;

import com.example.wuwenjun.pojo.ClassNews;


@Controller
public class ClassNewsController {

    @CrossOrigin
    @GetMapping(value = "/api/getpsv") //前端api接口
    @ResponseBody
    public StringBuilder GetPSV() {
        Socket socket = null;
        StringBuilder sb =null;
        try {
            InetAddress addr = InetAddress.getLocalHost();
            String host=addr.getHostName();
            //String ip=addr.getHostAddress().toString(); //获取本机ip
            //log.info("调用远程接口:host=>"+ip+",port=>"+12345);

            // 初始化套接字,设置访问服务的主机和进程端口号,HOST是访问python进程的主机名称,可以是IP地址或者域名,PORT是python进程绑定的端口号
            socket = new Socket(host,12345);

            // 获取输出流对象
            OutputStream os = socket.getOutputStream();
            PrintStream out = new PrintStream(os);
            // 发送内容
            out.print( "star");
            // 告诉服务进程,内容发送完毕,可以开始处理
            out.print("over");

            // 获取服务进程的输入流
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8"));
            String tmp = null;
            sb = new StringBuilder();
            // 读取内容
            while((tmp=br.readLine())!=null)
                sb.append(tmp).append('\n');
//            classNews = JSONArray.parseObject(sb.toString(),ClassNews.class);
//            System.out.println(classNews.getBase64code());
//            System.out.println(classNews.getName());
            System.out.println(sb);
            //将算法返回的结果再次返回给Vue前端
            return sb;
            // 解析结果
            //JSONArray res = JSON.parseArray(sb.toString());
        } catch (IOException e) {
            e.printStackTrace();
            return sb;
        }finally {
            try {
                if(socket!=null) socket.close();} catch (IOException e) {}
            System.out.println("远程接口调用结束.");
        }
    }

}

按照我上面的python算法返回的结果应该如下:
在这里插入图片描述

Vue前端代码

因为只是测试,所以我的前端写的很简陋,但是不影响功能,大家就当做测试来学习如何跑通Python,JavaWeb,Vue三方即可。这里给第一次尝试前端显示Base64图片的小白们提下,前端显示Base64的图片的src的格式为:
在这里插入图片描述前缀需要人为手动添加,具体方式参照下文:

<template>
  <div class="huaweisignup" style="width:1300px;height:1000px;background-color:yellow">
    <button @click="getPSV">点击获取算法处理结果</button>
    <div style="width:800px;height:800px;background-color:red">
      <!-- 图片显示区域 -->
      <img :src="base64code" style="margin-top:3%"/>
    </div>
  </div>
</template>

<script>
export default {
  name: 'HuaWeiSignUp',
  components: {
  },
  data () {
    return {
      base64code: ''
    }
  },
  created () {
    this.getPSV()
  },
  watch: {
  },
  methods: {
    getPSV () {
      //向后端发送get请求
      this.$axios.get('http://localhost:8443/api/getpsv').then(resp => {
        if (resp && resp.status === 200) {
          //状态码为200为请求成功
          //手动构造base64路径:前缀+返回码
          this.base64code = 'data:image/png;base64,' + resp.data.base64code
          this.$message({showClose: true, message: 'ok', type: 'success'})
          console.log(this.base64code)
        }
      })
    }
  }
}
</script>

最终效果

在这里插入图片描述

以上就是这期Python,SpringBoot,Vue三方交互的全部教程了,如果你耐心的看完了全部,那希望能帮助到勤奋耐心的你。

  • 23
    点赞
  • 137
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值