Python
Django
numpy
python3

Djangoで2枚の画像を合成する

More than 1 year has passed since last update.

概要:
Djangoでアップロードした画像と固定で決めた画像を合成をする処理。

処理:

import json
import numpy as np

import cv2
import os

def upload(request):
    try:
        req_file = request.FILES['image']

        file_path = '/tmp/'

        tmp_dir = file_path
        if not os.path.isdir(tmp_dir):
            os.makedirs(tmp_dir)


        path = os.path.join(tmp_dir, req_file.name)
        destination = open(path, 'wb')

        if req_file.size > 1048576:
            image_data = {
                'status': 400,
                'data': {
                    'message': '容量がオーバしています。',
                }
            }
            return JsonResponse(image_data)

        #アップした画像を書き込む
        for chunk in req_file.chunks():
            destination.write(chunk)

        image = cv2.imread(path)
        width, height = image.shape[:2]


        #上部の画像と合成をする処理
        size = width / 10 if width > height else height / 10
        size = int(size)
        margin = size / 5
        margin = int(margin)
        watermark = cv2.imread("上部の画像のフルパス", cv2.IMREAD_UNCHANGED)
        watermark = cv2.resize(watermark, (size, size))
        watermark_width, watermark_height = watermark.shape[:2]

        # 画像のアルファチャンネルだけ取り出す
        mask_ = watermark[:,:,3]
        # アルファチャンネルの値をBGRに格納したndarrayを作る
        mask = np.ones((watermark_width, watermark_height, 3))
        for i in range(len(mask)):
            for j in range(len(mask[0])):
                mask[i][j] = np.ones(3) * mask_[i][j]
        # 0~1になるように規格化
        mask = mask / 255.0
        # 値をfloatにキャストしておく。
        image = image.astype('float64')
        # アルファチャンネルはもういらないのでそれ以外を取り出す
        watermark = watermark[:,:,:3]
        # 指定の位置に画像を貼り込んで返す
        image[width - watermark_width -margin:width -margin, height - watermark_height -margin:height -margin] *= 1 - mask
        image[width - watermark_width -margin:width -margin, height - watermark_height -margin:height -margin] += mask * watermark


        root, ext = os.path.splitext(req_file.name)
        file_name = "test" + ext

        #合成した画像を書き込む
        cv2.imwrite(tmp_dir + '/' + file_name , image)

        image_data = {
            'status': 200,
            'data': {
                'name': req_file.name,
                'image_url': file_path + "/" + file_name,
                'size': req_file.size
            }
        }
        return JsonResponse(image_data)
    except:
        # 例外が発生したら、404を返す
        traceback.format_exc()
        return Http404("message")