[Python] OpenCV(cv2)の使い方を解説
OpenCVは、コンピュータビジョンや画像処理のためのライブラリで、Pythonでは cv2 モジュールとして利用されます。 画像の読み込みには cv2.imread() を使用し、表示には cv2.imshow() を用います。 画像の保存は cv2.imwrite() で行います。 また、画像のリサイズや回転、フィルタリングなどの操作も簡単に行えます。 OpenCVは、顔認識や物体検出などの高度な機能もサポートしており、機械学習やディープラーニングと組み合わせて利用されることが多いです。
OpenCV(cv2)とは
OpenCV(Open Source Computer Vision Library)は、コンピュータビジョンや画像処理のためのオープンソースライブラリです。
OpenCVの概要 特徴説明オープンソース無料で使用でき、コミュニティによって開発されている。クロスプラットフォームWindows、Linux、macOS、Android、iOSで動作する。多言語サポートC++、Python、Javaなど、複数のプログラミング言語に対応。リアルタイム処理高速な画像処理が可能で、リアルタイムアプリケーションに適している。 OpenCVの歴史 OpenCVの用途 用途説明画像処理画像のフィルタリング、変換、解析など。動画解析動画のフレーム処理、動体検知など。顔認識顔の検出や認識、表情分析など。物体追跡動体の追跡や識別。自動運転車両の周囲の認識や障害物検知。 OpenCVのインストール方法- Pythonがインストールされていることを確認します。
- コマンドラインで以下のコマンドを実行します。
これでOpenCVがインストールされ、 cv2 モジュールを使用できるようになります。
import cv2 print(cv2.__version__)OpenCVの基本操作
画像の読み込みと表示画像を読み込むには、 cv2.imread()関数 を使用します。
読み込んだ画像を表示するには、 cv2.imshow()関数 を使います。
import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # 画像の表示 cv2.imshow('Image', image) cv2.waitKey(0) cv2.destroyAllWindows() 画像の保存画像を保存するには、 cv2.imwrite()関数 を使用します。
import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # 画像の保存 cv2.imwrite('saved_image.jpg', image)このコードを実行すると、 image.jpg が saved_image.jpg として保存されます。
画像のサイズ変更画像のサイズを変更するには、 cv2.resize()関数 を使用します。
import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # 画像のサイズ変更 resized_image = cv2.resize(image, (300, 200)) # 画像の表示 cv2.imshow('Resized Image', resized_image) cv2.waitKey(0) cv2.destroyAllWindows()300 x 200に縮小したもの
画像の回転画像を回転させるには、 cv2.getRotationMatrix2D() と cv2.warpAffine() を使用します。
import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # 回転行列の作成 height, width = image.shape[:2] rotation_matrix = cv2.getRotationMatrix2D((width / 2, height / 2), 45, 1) # 画像の回転 rotated_image = cv2.warpAffine(image, rotation_matrix, (width, height)) # 画像の表示 cv2.imshow('Rotated Image', rotated_image) cv2.waitKey(0) cv2.destroyAllWindows() 画像の切り抜き import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # 画像の切り抜き (x, y, width, height) cropped_image = image[50:200, 100:300] # 画像の表示 cv2.imshow('Cropped Image', cropped_image) cv2.waitKey(0) cv2.destroyAllWindows()画像処理の基本
グレースケール変換カラー画像をグレースケール画像に変換するには、 cv2.cvtColor()関数 を使用します。
import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # グレースケール変換 gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 画像の表示 cv2.imshow('Gray Image', gray_image) cv2.waitKey(0) cv2.destroyAllWindows() 画像の二値化画像を二値化するには、 cv2.threshold()関数 を使用します。
import cv2 # 画像の読み込み image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # 画像の二値化 _, binary_image = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY) # 画像の表示 cv2.imshow('Binary Image', binary_image) cv2.waitKey(0) cv2.destroyAllWindows() 画像の平滑化(ぼかし)画像を平滑化するには、 cv2.GaussianBlur()関数 を使用します。
import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # 画像の平滑化 blurred_image = cv2.GaussianBlur(image, (5, 5), 0) # 画像の表示 cv2.imshow('Blurred Image', blurred_image) cv2.waitKey(0) cv2.destroyAllWindows() エッジ検出 import cv2 # 画像の読み込み image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # エッジ検出 edges = cv2.Canny(image, 100, 200) # 画像の表示 cv2.imshow('Edges', edges) cv2.waitKey(0) cv2.destroyAllWindows() 画像のヒストグラム画像のヒストグラムを表示するには、 cv2.calcHist()関数 を使用します。
import cv2 import numpy as np import matplotlib.pyplot as plt # 画像の読み込み image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # ヒストグラムの計算 histogram = cv2.calcHist([image], [0], None, [256], [0, 256]) # ヒストグラムの表示 plt.plot(histogram) plt.title('Histogram') plt.xlabel('Pixel Value') plt.ylabel('Frequency') plt.xlim([0, 256]) plt.show()画像の変換とフィルタリング
アフィン変換cv2.getAffineTransform() と cv2.warpAffine() を使用して実行します。
import cv2 import numpy as np # 画像の読み込み image = cv2.imread('image.jpg') # アフィン変換のための3点の指定 points1 = np.float32([[50, 50], [200, 50], [50, 200]]) points2 = np.float32([[10, 100], [200, 50], [100, 250]]) # アフィン変換行列の計算 matrix = cv2.getAffineTransform(points1, points2) # アフィン変換の適用 affine_transformed_image = cv2.warpAffine(image, matrix, (image.shape[1], image.shape[0])) # 画像の表示 cv2.imshow('Affine Transformed Image', affine_transformed_image) cv2.waitKey(0) cv2.destroyAllWindows() パースペクティブ変換cv2.getPerspectiveTransform() と cv2.warpPerspective() を使用します。
import cv2 import numpy as np # 画像の読み込み image = cv2.imread('image.jpg') # パースペクティブ変換のための4点の指定 points1 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]]) points2 = np.float32([[50, 50], [250, 30], [30, 250], [300, 300]]) # パースペクティブ変換行列の計算 matrix = cv2.getPerspectiveTransform(points1, points2) # パースペクティブ変換の適用 perspective_transformed_image = cv2.warpPerspective(image, matrix, (image.shape[1], image.shape[0])) # 画像の表示 cv2.imshow('Perspective Transformed Image', perspective_transformed_image) cv2.waitKey(0) cv2.destroyAllWindows() ガウシアンフィルタ import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # ガウシアンフィルタの適用 gaussian_blurred_image = cv2.GaussianBlur(image, (5, 5), 0) # 画像の表示 cv2.imshow('Gaussian Blurred Image', gaussian_blurred_image) cv2.waitKey(0) cv2.destroyAllWindows() メディアンフィルタ import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # メディアンフィルタの適用 median_blurred_image = cv2.medianBlur(image, 5) # 画像の表示 cv2.imshow('Median Blurred Image', median_blurred_image) cv2.waitKey(0) cv2.destroyAllWindows() バイラテラルフィルタ import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # バイラテラルフィルタの適用 bilateral_filtered_image = cv2.bilateralFilter(image, 9, 75, 75) # 画像の表示 cv2.imshow('Bilateral Filtered Image', bilateral_filtered_image) cv2.waitKey(0) cv2.destroyAllWindows()形状検出と解析
輪郭検出 import cv2 # 画像の読み込み image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # 画像の二値化 _, binary_image = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY) # 輪郭の検出 contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 輪郭の描画 contour_image = cv2.cvtColor(binary_image, cv2.COLOR_GRAY2BGR) cv2.drawContours(contour_image, contours, -1, (0, 255, 0), 2) # 画像の表示 cv2.imshow('Contours', contour_image) cv2.waitKey(0) cv2.destroyAllWindows() 形状の近似 import cv2 # 画像の読み込み image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # 画像の二値化 _, binary_image = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY) # 輪郭の検出 contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 形状の近似 approx_contours = [cv2.approxPolyDP(cnt, 10, True) for cnt in contours] # 近似した輪郭の描画 approx_image = cv2.cvtColor(binary_image, cv2.COLOR_GRAY2BGR) cv2.drawContours(approx_image, approx_contours, -1, (0, 255, 0), 2) # 画像の表示 cv2.imshow('Approximated Contours', approx_image) cv2.waitKey(0) cv2.destroyAllWindows() 形状の特徴量抽出cv2.contourArea() や cv2.arcLength() を使用して、面積や周囲の長さを計算します。
import cv2 # 画像の読み込み image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # 画像の二値化 _, binary_image = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY) # 輪郭の検出 contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 特徴量の抽出 for cnt in contours: area = cv2.contourArea(cnt) perimeter = cv2.arcLength(cnt, True) print(f'Area: , Perimeter: ') Area: 0.0, Perimeter: 0.0 Area: 0.0, Perimeter: 2.8284270763397217 Area: 0.0, Perimeter: 2.0 Area: 0.0, Perimeter: 2.0 Area: 0.0, Perimeter: 2.0 Area: 0.0, Perimeter: 0.0 . 各輪郭の面積と周囲の長さの結果が続く ハフ変換による直線検出ハフ変換を使用して画像内の直線を検出するには、 cv2.HoughLines() または cv2.HoughLinesP() を使用します。
import cv2 import numpy as np # 画像の読み込み image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # エッジ検出 edges = cv2.Canny(image, 50, 150) # ハフ変換による直線検出 lines = cv2.HoughLines(edges, 1, np.pi / 180, 100) # 直線の描画 line_image = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR) if lines is not None: for rho, theta in lines[:, 0]: a = np.cos(theta) b = np.sin(theta) x0 = a * rho y0 = b * rho x1 = int(x0 + 1000 * (-b)) y1 = int(y0 + 1000 * (a)) x2 = int(x0 - 1000 * (-b)) y2 = int(y0 - 1000 * (a)) cv2.line(line_image, (x1, y1), (x2, y2), (0, 255, 0), 2) # 画像の表示 cv2.imshow('Hough Lines', line_image) cv2.waitKey(0) cv2.destroyAllWindows() ハフ変換による円検出ハフ変換を使用して画像内の円を検出するには、 cv2.HoughCircles() を使用します。
import cv2 import numpy as np # 画像の読み込み image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # エッジ検出 blurred_image = cv2.GaussianBlur(image, (9, 9), 2) circles = cv2.HoughCircles(blurred_image, cv2.HOUGH_GRADIENT, dp=1, minDist=20, param1=50, param2=30, minRadius=0, maxRadius=0) # 円の描画 color_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR) if circles is not None: circles = np.uint16(np.around(circles)) for i in circles[0, :]: # 円の外周 cv2.circle(color_image, (i[0], i[1]), i[2], (0, 255, 0), 2) # 円の中心 cv2.circle(color_image, (i[0], i[1]), 2, (0, 0, 255), 3) # 画像の表示 cv2.imshow('Hough Circles', color_image) cv2.waitKey(0) cv2.destroyAllWindows()画像の特徴量抽出
SIFT(Scale-Invariant Feature Transform) import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # SIFTオブジェクトの作成 sift = cv2.SIFT_create() # 特徴点と特徴量の検出 keypoints, descriptors = sift.detectAndCompute(image, None) # 特徴点の描画 sift_image = cv2.drawKeypoints(image, keypoints, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) # 画像の表示 cv2.imshow('SIFT Keypoints', sift_image) cv2.waitKey(0) cv2.destroyAllWindows() SURF(Speeded-Up Robust Features) import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # SURFオブジェクトの作成 surf = cv2.xfeatures2d.SURF_create() # 特徴点と特徴量の検出 keypoints, descriptors = surf.detectAndCompute(image, None) # 特徴点の描画 surf_image = cv2.drawKeypoints(image, keypoints, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) # 画像の表示 cv2.imshow('SURF Keypoints', surf_image) cv2.waitKey(0) cv2.destroyAllWindows()SURFアルゴリズムは特許で保護されているため、通常のOpenCVでは使用できません。使用する場合は、OpenCV とOpenCV ContribをGithubのリポジトリをクローンし、ビルドしたものを使用してください。
Open Source Computer Vision Library. Contribute to opencv/opencv development by creating an account on GitHub.
Repository for OpenCV's extra modules. Contribute to opencv/opencv_contrib development by creating an account on GitHub.
ORB(Oriented FAST and Rotated BRIEF) import cv2 # 画像の読み込み image = cv2.imread('image.jpg') # ORBオブジェクトの作成 orb = cv2.ORB_create() # 特徴点と特徴量の検出 keypoints, descriptors = orb.detectAndCompute(image, None) # 特徴点の描画 orb_image = cv2.drawKeypoints(image, keypoints, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) # 画像の表示 cv2.imshow('ORB Keypoints', orb_image) cv2.waitKey(0) cv2.destroyAllWindows() 特徴量マッチング import cv2 # 画像の読み込み image1 = cv2.imread('image1.jpg') image2 = cv2.imread('image2.jpg') # SIFTオブジェクトの作成 sift = cv2.SIFT_create() # 特徴点と特徴量の検出 keypoints1, descriptors1 = sift.detectAndCompute(image1, None) keypoints2, descriptors2 = sift.detectAndCompute(image2, None) # BFMatcherの作成 bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True) # 特徴量のマッチング matches = bf.match(descriptors1, descriptors2) # マッチング結果の描画 matches = sorted(matches, key=lambda x: x.distance) matching_image = cv2.drawMatches(image1, keypoints1, image2, keypoints2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS) # 画像の表示 cv2.imshow('Feature Matching', matching_image) cv2.waitKey(0) cv2.destroyAllWindows()動画処理
動画の読み込みと表示動画を読み込むには、 cv2.VideoCapture() を使用します。
import cv2 # 動画の読み込み cap = cv2.VideoCapture('video.mp4') while cap.isOpened(): ret, frame = cap.read() if not ret: break # フレームの表示 cv2.imshow('Video', frame) # 'q'キーで終了 if cv2.waitKey(1) & 0xFF == ord('q'): break # リソースの解放 cap.release() cv2.destroyAllWindows() フレームの取得と保存動画から特定のフレームを取得し、保存するには、 cv2.VideoCapture() と cv2.imwrite() を使用します。
import cv2 # 動画の読み込み cap = cv2.VideoCapture('video.mp4') # 最初のフレームの取得 ret, frame = cap.read() if ret: cv2.imwrite('first_frame.jpg', frame) # リソースの解放 cap.release()このコードを実行すると、動画の最初のフレームが first_frame.jpg として保存されます。
動画の書き出し動画を新しいファイルに書き出すには、 cv2.VideoWriter() を使用します。
import cv2 # 動画の読み込み cap = cv2.VideoCapture('video.mp4') # 動画の書き出し設定 fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('output_video.avi', fourcc, 20.0, (int(cap.get(3)), int(cap.get(4)))) while cap.isOpened(): ret, frame = cap.read() if not ret: break # フレームを書き出し out.write(frame) # リソースの解放 cap.release() out.release() cv2.destroyAllWindows()このコードを実行すると、 output_video.avi という新しい動画ファイルが作成されます。
動画のフィルタリング import cv2 # 動画の読み込み cap = cv2.VideoCapture('video.mp4') # 動画の書き出し設定 fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('filtered_video.avi', fourcc, 20.0, (int(cap.get(3)), int(cap.get(4)))) while cap.isOpened(): ret, frame = cap.read() if not ret: break # ガウシアンフィルタの適用 filtered_frame = cv2.GaussianBlur(frame, (5, 5), 0) # フレームを書き出し out.write(filtered_frame) # リソースの解放 cap.release() out.release() cv2.destroyAllWindows()このコードを実行すると、各フレームにガウシアンフィルタが適用された filtered_video.avi という新しい動画ファイルが作成されます。
動体検知 import cv2 # 動画の読み込み cap = cv2.VideoCapture('video.mp4') # 背景差分オブジェクトの作成 fgbg = cv2.createBackgroundSubtractorMOG2() while cap.isOpened(): ret, frame = cap.read() if not ret: break # 背景差分の適用 fgmask = fgbg.apply(frame) # 動体の表示 cv2.imshow('Motion Detection', fgmask) # 'q'キーで終了 if cv2.waitKey(30) & 0xFF == ord('q'): break # リソースの解放 cap.release() cv2.destroyAllWindows()応用例
顔検出と顔認識 import cv2 # Haarカスケード分類器の読み込み face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') # 画像の読み込み image = cv2.imread('image.jpg') gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 顔の検出 faces = face_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=5) # 検出した顔の描画 for (x, y, w, h) in faces: cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2) # 画像の表示 cv2.imshow('Face Detection', image) cv2.waitKey(0) cv2.destroyAllWindows() 物体検出と追跡YOLO(You Only Look Once)やSSD(Single Shot MultiBox Detector)などの深層学習モデルを使用することが一般的です。
import cv2 import numpy as np # YOLOの設定ファイルと重みファイルの読み込み net = cv2.dnn.readNet('yolov3.weights', 'yolov3.cfg') layer_names = net.getLayerNames() output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()] # 画像の読み込み image = cv2.imread('image.jpg') height, width = image.shape[:2] # 画像をBlobに変換 blob = cv2.dnn.blobFromImage(image, 0.00392, (416, 416), (0, 0, 0), True, crop=False) net.setInput(blob) # 物体検出 outs = net.forward(output_layers) # 検出結果の描画 for out in outs: for detection in out: scores = detection[5:] class_id = np.argmax(scores) confidence = scores[class_id] if confidence > 0.5: center_x = int(detection[0] * width) center_y = int(detection[1] * height) w = int(detection[2] * width) h = int(detection[3] * height) x = int(center_x - w / 2) y = int(center_y - h / 2) cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) # 画像の表示 cv2.imshow('Object Detection', image) cv2.waitKey(0) cv2.destroyAllWindows() 画像のセグメンテーション以下のサンプルコードでは、 K-meansクラス タリングを使用して画像のセグメンテーションを行います。
import cv2 import numpy as np # 画像の読み込み image = cv2.imread('image.jpg') Z = image.reshape((-1, 3)) # K-meansクラスタリングの適用 K = 3 Z = np.float32(Z) criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2) _, labels, centers = cv2.kmeans(Z, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) # セグメンテーション結果の生成 centers = np.uint8(centers) segmented_image = centers[labels.flatten()] segmented_image = segmented_image.reshape(image.shape) # 画像の表示 cv2.imshow('Segmented Image', segmented_image) cv2.waitKey(0) cv2.destroyAllWindows()このコードを実行すると、 K-meansクラス タリングによってセグメンテーションされた画像が表示されます。
OCR(光学文字認識) import cv2 import pytesseract # 画像の読み込み image = cv2.imread('text_image.jpg') # OCRの実行 text = pytesseract.image_to_string(image, lang='eng') # 認識したテキストの表示 print('Recognized Text:', text) 画像のスタイル変換 import cv2 import numpy as np # スタイル変換のためのモデルの読み込み net = cv2.dnn.readNetFromTorch('models/instance_norm/mosaic.t7') # 画像の読み込み content_image = cv2.imread('content.jpg') style_image = cv2.imread('style.jpg') # 画像をBlobに変換 blob = cv2.dnn.blobFromImage(content_image, 1.0, (content_image.shape[1], content_image.shape[0]), (103.939, 116.779, 123.68), swapRB=False, crop=False) net.setInput(blob) # スタイル変換の実行 output = net.forward() # 出力画像の整形 output = output.reshape((output.shape[2], output.shape[3], output.shape[1])) output += np.array((103.939, 116.779, 123.68)) output = np.clip(output, 0, 255).astype('uint8') # 画像の表示 cv2.imshow('Styled Image', output) cv2.waitKey(0) cv2.destroyAllWindows()