python中使用flask实现与linux服务器的数据交互

前段时间使用opencv的时候,想在pycharm中显示服务器端代码运行处理后的图片或者视频,但是报错"can not connect X server"。之前使用了远程桌面的方法,直接访问远程服务端的桌面,在远程直接编译显示处理后的图片。
链接如下:ubuntu16使用Remmina访问远程linux服务器桌面
但是这个方法对于服务器在云上的程序员来说或许不是很友好,于是在百度后,发现了可以通过flask库,把我们要运行的代码设置为api,通过访问该api,可以从服务端返回图片数据到本地,之后本地通过解码后即可显示。
话不多说,下面我用ip摄像头获取的图片的代码说明下如何操作。

本地客户端中的代码如下

import requests
import cv2
import base64
import json
import  numpy

#这是我们要访问的API地址以及端口
url = "http://192.168.zzz.xxx:yyyy" 
#把opencv读(read)到的图的像素矩阵转为base64编码
def image_to_base64(img_np):
    #在对像素矩阵进行base64编码时,需要先把图片编码成十六进制数据流
    img_code = cv2.imencode('.jpg', img_np)[1]
    img_code64 = base64.b64encode(img_code)
    return img_code64
    
#base64编码转为opencv可以show的像素矩阵
def base64_to_img(base64code):
    #需要先解码base64为十六进制数据流
    img_data = base64.b64decode(base64code)
    #把十六进制转化为opencv可以解码的十进制整型数据流
    img_array = numpy.fromstring(img_data, numpy.uint8)
    #解码为mat像素矩阵
    img =cv2.imdecode(img_array, cv2.COLOR_RGB2BGR)
    return img
    
#byte数据转为字符串
def byte_to_str(byte):
    str_ = str(byte)[2:]
    return str_
    
#字符串转为byte数据
def str_to_byte(str_data):
    byte = bytes(str_data, encoding='utf8')
    return byte
    
#通过post把摄像头的图片上传到服务端
def post_ipcam(img_array):
    #这里我们使用了json数据,所以要把base64编码转化为字符串
    img_64code = str(image_to_base64(img_array))[2:]
    res = {"image": img_64code} 
    json_res = json.dumps(res)
    result = requests.post(url, data=json_res) #result为远程服务端处理后返回的结果
    return result

rtsp = "rtsp://摄像头账户:摄像头密码@ip摄像头的地址和端口/MPEG/ch1/main/av_stream"
camera = cv2.VideoCapture(rtsp)
while True:
    #img_array是opencv读取到的像素矩阵
    ret_val, img_array = camera.read()
    camera.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M', 'J', 'P', 'G'))
    #之前使用摄像头rtsp流遇到断流的情况,于是现在都留了一手,断流后再重新建立rtsp流
    if not ret_val: 
        camera = cv2.VideoCapture(rtsp)
        camera.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M', 'J', 'P', 'G'))
        ret_val, img_array = camera.read()
        continue
    res = post_ipcam(img_array)
    #其中res返回的是处理后的图像的base64编码的字符串
    res_img_b64bytes = res._content 
    #把base64编码解码为opencv可以show的像素矩阵
    img = base64_to_img(res_img_b64bytes)   
    #把图片show出来就可以了,完美解决can not connect to X server
    cv2.imshow('', img)
    cv2.waitKey(1)

服务端中的代码如下

重点是**@app.route("/", methods=[‘POST’])**下的代码,这是要操作的主要服务端代码

from flask import request, Flask
import base64
import json
import cv2
import numpy
app = Flask(__name__)

def image_to_base64(img_np):
    img = cv2.imencode('.jpg', img_np)[1]
    img_code64 = base64.b64encode(img)
    return img_code64

def base64_to_img(base64code):
    img_data = base64.b64decode(base64code)
    img_array = numpy.fromstring(img_data, numpy.uint8)
    img =cv2.imdecode(img_array, cv2.COLOR_RGB2BGR)
    return img

def str_to_byte(str_data):
    byte = bytes(str_data, encoding='utf8')
    return byte

def byte_to_str(byte):
    str_ = str(byte)[2:]
    return str_

class Flag:  #这里设置了静态类定义了Flag,用于跳帧处理上传的图像,as your will
    process_this_frame = 2
    def changeFlag(self):
        if Flag.process_this_frame != 2:
            Flag.process_this_frame = Flag.process_this_frame +1
        elif Flag.process_this_frame == 2:
            Flag.process_this_frame = 0

class TMP: # 这里我设置了静态类来暂时保存数据,as your will
    tmp_res = []
    def set_tmp(self, res):
        TMP.tmp_res = res

@app.route("/", methods=['POST'])
def get_frame():
    flag = Flag()
    tmp = TMP()
    #因为上传的是json数据,所以我们使用json.load来加载request中的data。为什么是request.data,因为requests.post(url, **data**=json_res)
    json_data = json.loads(request.data)
    if json_data:
        #json解码为opencv可以处理的像素矩阵
        byte =str_to_byte(json_data["image"])
        img = base64_to_img(byte)
        if flag.process_this_frame == 2:
            flag.changeFlag()            
            ###
            一顿操作后,得到了处理后的图像的像素矩阵img_res
            ###
            base64_img = image_to_base64(img_res)
            #返回的数据流只能是字符串,故要把base64转换为string
            res_imgstr = byte_to_str(base64_img)
        elif flag.process_this_frame != 2:
             ###
            一顿操作后,得到了处理后的图像的像素矩阵img_res
            ###
            base64_img = image_to_base64(img_res)
            res_imgstr = byte_to_str(base64_img)
        #返回字符串到客户端
        return res_imgstr
    else:
        return 'fail'

if __name__ == "__main__":
	# 本地客户端中写的API的地址和端口
    app.run("192.168.zzz.xxx", port=yyyy)

这里有两部分代码,所以看的时候可能有点绕,如果有疑问或者哪里有问题可以提一下。帮到你的话小手点个赞哈

你可能感兴趣的:(计算机视觉,opencv)