Darkside(https対応しました)

2022年6月11日(土) 21:13

DUAL FISHEYE 静止画ステッチソフト(改)

 位相限定相関法による左右の上下ズレ取得は、驚くほどうまく機能した。
 上下ズレの調整はフルオートにしてしまい、左右画像を自動切り出し保存して仕上がりを確認だけできるようにした。倍率色収差も低減させる。
 基本的に、8192x5464で保存された画像なら何で撮影したものであろうと処理する。
 RAW現像してTIFF8ビットで保存したものを読ませる想定。16ビットにしても、コード改変や処理時間増大に見合った効果は無いと判断した。
 出力ファイルは png がお薦め。

 以下は完全なソースリストだが、パラメーターは自分の所有個体決め打ちなので、他機材だとパラメーターを修正しないとベストな仕上がりにならない点が要注意。

import sys
import numpy as np
import cv2
import argparse
parser = argparse.ArgumentParser(description='VR180 3D 撮影した静止画のステッチ')
parser.add_argument('infile', help='入力画像ファイル名')
parser.add_argument('outfile', help='出力画像ファイル名')
args = parser.parse_args()
dm_w = 4096
dm_h = 4096
dfish = 3684
width = 8192
height = 5464
arr_sin_dm_phi = [np.pi] * (dm_w * 2)
arr_cos_dm_phi = [np.pi] * (dm_w * 2)
xmap = np.zeros((dm_h, dm_w), np.float32)
ymap = np.zeros((dm_h, dm_w), np.float32)
try:
    # try to load map file
    xmap = np.load("xmap.npy")
    ymap = np.load("ymap.npy")
except IOError:
    # if the map files are not exist, generate new map files.
    print("Generating map files...")
    for x in range(dm_w * 2):
        dm_x = float(x)
        dm_phi = np.pi * 2.0 * dm_x / dm_w / 2.0
        arr_sin_dm_phi[x] = np.sin(dm_phi)
        arr_cos_dm_phi[x] = np.cos(dm_phi)
    for y in range(dm_h):
        dm_y = float(y)
        dm_theta = np.pi * dm_y / (dm_h-1)
        sin_dm_theta = np.sin(dm_theta)
        cos_dm_theta = np.cos(dm_theta)
        xst = int(dm_w / 2)
        xen = int(dm_w * 3 / 2)
        for x in range(xst,xen):
            dm_x = float(x)
            sin_dm_phi = arr_sin_dm_phi[x]
            cos_dm_phi = arr_cos_dm_phi[x]
            tmp2_x = sin_dm_theta * cos_dm_phi
            tmp2_y = sin_dm_theta * -sin_dm_phi
            tmp2_z = cos_dm_theta
            tmp_x = tmp2_x
            tmp_y = tmp2_y
            tmp_z = tmp2_z
            tmp2_x = tmp_x
            tmp2_y = tmp_y
            tmp2_z = tmp_z
            car_x = tmp2_x
            car_y = tmp2_y
            car_z = tmp2_z
            tmp_x = car_x
            tmp_y = car_y
            tmp_z = car_z
            car_x = tmp_z;
            car_y = tmp_y;
            car_z = -tmp_x;
            dm_theta = np.arccos(car_z)
            if (car_y > 0):
                dm_phi = np.arctan(car_x / car_y)
            elif (car_y < 0):
                dm_phi = np.pi - np.arctan(car_x / -car_y)
            elif (car_y == 0 and car_x > 0):
                dm_phi = np.pi / 2.0
            elif (car_y == 0 and car_x < 0):
                dm_phi = -np.pi / 2.0
            else:
                dm_phi = 0
            xmap[y,x-xst] = (dm_theta / (np.pi) * np.cos(-dm_phi)) * float(dfish) + float(dfish/2)
            ymap[y,x-xst] = (dm_theta / (np.pi) * np.sin(-dm_phi)) * float(dfish) + float(dfish/2)
    np.save("xmap.npy", xmap)
    np.save("ymap.npy", ymap)
xmapL = np.zeros((dm_h, dm_w), np.float32)
ymapL = np.zeros((dm_h, dm_w), np.float32)
xmapR = np.zeros((dm_h, dm_w), np.float32)
ymapR = np.zeros((dm_h, dm_w), np.float32)
# ステッチ中心
LX = 2114
LY = 2707
RX = 1982
# 収差補正中心
CLX = 1808
CLY = 2592
CRX = 2113
CRY = 2913
# 上下ズレ判定範囲
W2 = 1800 # 判定範囲横幅
H1 = 1000 # 判定範囲TOP
H2 = 3400 # 判定範囲Height
img = cv2.imread(args.infile)
img_left = img[0:height, int(width/2):width]
img_right = img[0:height, 0:int(width/2)]
img_leftp = img_left[H1:H1+H2, int(LX - W2/2):int(LX + W2/2)]
img_rightp = img_right[H1:H1+H2, int(RX - W2/2):int(RX + W2/2)]
grey_left = cv2.cvtColor(img_leftp, cv2.COLOR_BGR2GRAY)
grey_right = cv2.cvtColor(img_rightp, cv2.COLOR_BGR2GRAY)
# 位相限定相関法
(dx, dy), response = cv2.phaseCorrelate(grey_left .astype(np.float32), grey_right .astype(np.float32))
print("ズレ=" + str(dy))
mat = np.array([[1.0, 0.0, 0.0], [0.0, 1.0, -dy]], dtype=float)
out = cv2.warpAffine(img_rightp, mat, (W2, H2))
# ズレ判定が適切かどうかの確認用画像
cv2.imwrite('L.png', img_leftp)
cv2.imwrite('R.png', out)
RY = LY + dy # ここを書き換えれば任意の上下ズレ量にできる
CX = LX - dfish / 2
CY = LY - dfish / 2
for i in range(len(xmapL)):
    xmapL[i] = xmap[i] + CX
for i in range(len(ymapL)):
    ymapL[i] = ymap[i] + CY
CX = RX - dfish / 2
CY = RY - dfish / 2
for i in range(len(xmapR)):
    xmapR[i] = xmap[i] + CX
for i in range(len(ymapR)):
    ymapR[i] = ymap[i] + CY
# 倍率色収差の補正
MAG_RED = 1.00055
WARP_FLAGS = cv2.INTER_LANCZOS4 # Lanczos 補間
im_bgr = cv2.split(img_left) # B=im_bgr[0] R=im_bgr[1] G=im_bgr[2]
M = cv2.getRotationMatrix2D((CLX, CLY), 0, MAG_RED)
img_red = cv2.warpAffine(im_bgr[1], M, (int(width/2), height), flags=WARP_FLAGS)
im = cv2.merge((im_bgr[0], img_red, im_bgr[2]))
left = cv2.remap(im, xmapL, ymapL, WARP_FLAGS, cv2.BORDER_CONSTANT)
im_bgr = cv2.split(img_right) # B=im_bgr[0] R=im_bgr[1] G=im_bgr[2]
M = cv2.getRotationMatrix2D((CRX, CRY), 0, MAG_RED)
img_red = cv2.warpAffine(im_bgr[1], M, (int(width/2), height), flags=WARP_FLAGS)
im = cv2.merge((im_bgr[0], img_red, im_bgr[2]))
right = cv2.remap(im, xmapR, ymapR, WARP_FLAGS, cv2.BORDER_CONSTANT)
om = cv2.hconcat([left, right])
cv2.imwrite(args.outfile, om)

 倍率色収差はRプレーンしか修正していない。
 また、Rプレーンを拡大する際の中心座標は、収差補正中心とコメントしてある部分。自分の所有個体は明らかに左右の中心座標が非対称。ここキッチリと調査しないと、画質は改善されない。仮にこれが個体差による偏芯によるものであれば、キヤノン公式のレンズデーターが今後も提供されない可能性がある。

 パラメーターさえ正確なら、EOS VR Utility より出力品質は上になる(はず)。

written by higashino [Virtual Reality] [この記事のURL] [コメントを書く] [コメント(0)] [TB(0)]

この記事へのトラックバックPingURL

Comments

TrackBacks

Darkside(https対応しました)

Generated by MySketch GE 1.4.1

Remodelling origin is MySketch 2.7.4