LoginSignup
24
21

More than 3 years have passed since last update.

Pythonで画像データをJSONにしてネットワーク越しに送受信する

Posted at

はじめに

 Webカメラで撮った画像をHTTPの通信を介して顔検出モデル等が動いている別のサーバーに送信するようなコードを何度か書いたので忘れないようにメモする。
 サンプルコードでは、送信側でWebカメラから撮った画像を一定間隔でサーバに送信し、受信側で顔を検出してボックスを描画した上でローカルに画像ファイルを保存している。

送信側

sender.py
import numpy as np
import cv2
import time
import json
import base64
import requests

def send_image(img):
  # 画像を送信可能な形式に変換してJSONに格納
  _, encimg = cv2.imencode(".png", img)
  img_str = encimg.tostring()
  img_byte = base64.b64encode(img_str).decode("utf-8")
  img_json = json.dumps({'image': img_byte}).encode('utf-8')

  # HTTPリクエストを送信
  response = requests.post("http://localhost:8080/save", data=img_json)
  print('{0} {1}'.format(response.status_code, json.loads(response.text)["message"]))

if __name__ == '__main__':
  cap = cv2.VideoCapture(0)
  cap.set(cv2.CAP_PROP_FPS, 30)
  i = 0
  while True:
    _, img = cap.read()
    if i % 5 == 0:
      send_image(img)
    i += 1

受信側

receiver.py
import os
import json
import cv2
import base64
import numpy as np
from datetime import datetime
from flask import Flask, request, Response
app = Flask(__name__)
count = 0

# 画像を保存するフォルダの作成
image_dir = "./images"
if not os.path.isdir(image_dir):
  os.mkdir(image_dir)

def detect_face(img):
  # 顔検出モデル('haarcascade_frontalface_default.xml')は下記リンクからダウンロードできる
  # https://github.com/opencv/opencv/tree/master/data/haarcascades
  face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
  faces = face_cascade.detectMultiScale(img, 1.3, 5)
  return faces

@app.route('/save', methods=['POST'])
def save_image():
    # データの変換処理
    data = request.data.decode('utf-8')
    data_json = json.loads(data)
    image = data_json['image']
    image_dec = base64.b64decode(image)
    data_np = np.fromstring(image_dec, dtype='uint8')
    decimg = cv2.imdecode(data_np, 1)

    # 顔検出してボックスを描画
    gray_img = cv2.cvtColor(decimg, cv2.COLOR_BGR2GRAY)
    faces = detect_face(gray_img)
    for (x,y,w,h) in faces:
      decimg = cv2.rectangle(decimg,(x,y),(x+w,y+h),(255,0,0),2)

    # 画像ファイルを保存
    global count
    filename = "./images/image{}.png".format(count)
    cv2.imwrite(filename, decimg)
    count += 1

    # HTTPレスポンスを送信
    return Response(response=json.dumps({"message": "{} was saved".format(filename)}), status=200)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

参考

http://edosha.hatenablog.jp/entry/2017/09/05/174453
https://ysss.hateblo.jp/entry/2018/07/31/053507

24
21
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
21