openCVライブラリとpythonを使用して、写真とビデオから放射状の歪みを除去します

この記事では、コンピュータービジョンライブラリ(openCV)を使用して、写真やビデオから放射状の歪み(歪み)の影響を除去する方法について説明します。 この効果は、魚眼効果または歪み効果とも呼ばれます。 この記事を書く決定は、インターネット上で情報を検索して数日後に行われました。 英語のガイドがあるにもかかわらず、すべてが機能するようにopenCVを正しくインストールする方法を説明していません。 この記事には既製のコードが含まれています。







すぐに最終結果の写真を持参してください。 左側は元の写真、右側は処理済みです:







前に後









openCVをビルドしてインストールする



最初にすることは、openCVライブラリを正しくインストールすることです。 これを行うには、公式リポジトリからopenCVopencv_contribの 2つのプロジェクトをダウンロードします。







git clone https://github.com/opencv/opencv.git git clone https://github.com/opencv/opencv_contrib.git
      
      





openCVの読み込み中に、ffmpegビデオコーデックをインストールします。







 sudo apt-get install ffmpeg
      
      





openCVフォルダーに移動し、サブフォルダーbuidを作成してそこに移動します。 openCVライブラリのアセンブリおよびインストールに関するすべての作業は、このディレクトリから行われます。







 cd opencv mkdir build cd build/
      
      





ライブラリをビルドするには、次のコマンドを実行します。







 cmake .. -DOPENCV_EXTRA_MODULES_PATH=/   opencv_contrib/modules/ /   opencv/ make -j5 sudo make install
      
      





構築に約1時間半かかり、インストールには数分かかりました。 注:アセンブリ中にエラーが発生した場合(cmakeコマンドが実行された場合)、新しい開始のためにCMakeCache.txtファイルを削除する必要があります。 インストール後、すべてが正しく行われたかどうかを確認できます。 これを行うには、Pythonランタイムを呼び出して、openCVライブラリをインポートします。 エラーが発生していなければ、すべてを正しく行いました。 2行目には、インストールしたバージョンが表示されます。 この記事を書いている時点では、ライブラリのバージョン3を使用していました。







 import cv2 print ("OpenCV version : {0}".format(cv2.__version__))
      
      





カメラキャリブレーション



歪みを除去するには、カメラのキャリブレーション係数を決定する必要があります。 これを行うには、 チェス盤を使用して写真をダウンロードし、カメラで5〜6枚の写真を撮影する必要があります。この画像を処理します。 すべての画像をpng形式に変換する必要があります 。 次に、次のコードを実行します。







補正係数の決定
 from __future__ import print_function import numpy as np import cv2 from common import splitfn import os if __name__ == '__main__': import sys import getopt from glob import glob args, img_mask = getopt.getopt(sys.argv[1:], '', ['debug=', 'square_size=']) args = dict(args) args.setdefault('--debug', '/ /') args.setdefault('--square_size', 1.0) if not img_mask: img_mask = '/  /*.png' else: img_mask = img_mask[0] img_names = glob(img_mask) debug_dir = args.get('--debug') if not os.path.isdir(debug_dir): os.mkdir(debug_dir) square_size = float(args.get('--square_size')) pattern_size = (9, 6) pattern_points = np.zeros((np.prod(pattern_size), 3), np.float32) pattern_points[:, :2] = np.indices(pattern_size).T.reshape(-1, 2) pattern_points *= square_size obj_points = [] img_points = [] h, w = 0, 0 img_names_undistort = [] for fn in img_names: print('processing %s... ' % fn, end='') img = cv2.imread(fn, 0) if img is None: print("Failed to load", fn) continue h, w = img.shape[:2] found, corners = cv2.findChessboardCorners(img, pattern_size) if found: term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1) cv2.cornerSubPix(img, corners, (5, 5), (-1, -1), term) if not found: print('chessboard not found') continue img_points.append(corners.reshape(-1, 2)) obj_points.append(pattern_points) print('ok') rms, camera_matrix, dist_coefs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, (w, h), None, None) print("\nRMS:", rms) print("camera matrix:\n", camera_matrix) print("distortion coefficients: ", dist_coefs.ravel()) cv2.destroyAllWindows()
      
      





このスクリプトを実行すると、処理された写真に関するメッセージがコンソールに表示され、カメラマトリックスと歪み係数という2つの重要なパラメーターが表示されます。 これらが必要なキャリブレーション係数です。







コーフ



写真およびビデオ処理



写真やビデオを処理するには、以下のスクリプトを実行する必要があります。 スクリプトでは、キャリブレーションパラメーターと作業フォルダーを指定する必要があります。







写真処理用のスクリプト
 from __future__ import print_function import numpy as np import cv2 import glob from matplotlib import pyplot as plt from common import splitfn import os img_names_undistort = [img for img in glob.glob("/    /*.png")] new_path = "/    /" camera_matrix = np.array([[1.26125746e+03, 0.00000000e+00, 9.40592038e+02], [0.00000000e+00, 1.21705719e+03, 5.96848905e+02], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]); dist_coefs = np.array([-0.49181345, 0.25848255, -0.01067125, -0.00127517, -0.01900726]); i = 0 #for img_found in img_names_undistort: while i < len(img_names_undistort): img = cv2.imread(img_names_undistort[i]) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) h, w = img.shape[:2] newcameramtx, roi = cv2.getOptimalNewCameraMatrix(camera_matrix, dist_coefs, (w, h), 1, (w, h)) dst = cv2.undistort(img, camera_matrix, dist_coefs, None, newcameramtx) dst = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB) # crop and save the image x, y, w, h = roi dst = dst[y:y+h-50, x+70:x+w-20] name = img_names_undistort[i].split("/") name = name[6].split(".") name = name[0] full_name = new_path + name + '.jpg' #outfile = img_names_undistort + '_undistorte.png' print('Undistorted image written to: %s' % full_name) cv2.imwrite(full_name, dst) i = i + 1
      
      





ビデオ処理用のスクリプト
 from __future__ import print_function import numpy as np import cv2 import glob from matplotlib import pyplot as plt from common import splitfn import os FILENAME_IN = "videoin.mp4" FILENAME_OUT = "videoout.mp4" CODEC = 'mp4v' camera_matrix = np.array([[1.26125746e+03, 0.00000000e+00, 9.40592038e+02], [0.00000000e+00, 1.21705719e+03, 5.96848905e+02], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]); dist_coefs = np.array([-3.18345478e+01, 7.26874187e+02, -1.20480816e-01, 9.43789095e-02, 5.28916586e-01]); print ("OpenCV version : {0}".format(cv2.__version__)) print((cv2.__version__).split('.')) # Load video video = cv2.VideoCapture(FILENAME_IN) fourcc = cv2.VideoWriter_fourcc(*list(CODEC)) fps = video.get(cv2.CAP_PROP_FPS) frame_count = video.get(cv2.CAP_PROP_FRAME_COUNT) size = (int(video.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))) sizew = (1676, 846) writer = cv2.VideoWriter(FILENAME_OUT, fourcc, 25, sizew) newcameramtx, roi = cv2.getOptimalNewCameraMatrix(camera_matrix, dist_coefs, (size[0], size[1]), 1, (size[0], size[1])) x, y, w, h = roi M = cv2.getRotationMatrix2D((size[0]/2,size[1]/2),5,1) while video.grab() is True: print("On frame %i of %i."%(video.get(cv2.CAP_PROP_POS_FRAMES), frame_count)) frame = video.retrieve()[1] frame = cv2.undistort(frame, camera_matrix, dist_coefs, None, newcameramtx) frame = frame[y:y+h-50, x+70:x+w-20] writer.write(frame) video.release() writer.release()
      
      






All Articles