Python + OpenCV로 야구 공을 추적
대부분 전에 자바에서 야구 공을 추적하고 있었기 때문에 이번에는 파이썬으로 시도했습니다.
추적은 배경 차이와 템플릿 매칭을 결합하여 수행됩니다.
환경 구축
환경은 다음과 같습니다.
venv
에서 환경을 만들고 있습니다. venv
그렇지 않아도 문제 없습니다.$ python -m venv pythonOpevCV
$ cd pythonOpenCV
$ Script\activate
$ python -m pip install --upgrade pip
$ pip install opencv-python
Successfully installed numpy-1.18.2 opencv-python-4.2.0.34
numpy
도 설치됩니다.준비하는 것
다음을 준비하십시오.
공을 잘라낸 이미지는 다음과 같이 괜찮습니다. 이하 견본입니다.
절차
다음 절차에 따라 추적을 수행합니다.
갑자기 오리지날의 프레임 화상에 대해서 템플릿 매칭을 실시해도, 구름이나 배경의 건물을 볼과 잘못해 검출해 버려, 정밀도가 좋지 않기 때문에 그레이 스케일→2치화로 흑백의 화상으로 합니다. 그 흑백 화상 상태에서 전후의 프레임으로 배경 차분을 실시하면, 구름이나 배경은 0.1초 정도에서는 거의 움직이지 않기 때문에 이동하고 있는 볼을 확실히 검출할 수 있습니다.
회색조 이미지는 다음과 같습니다.
빨간색 테두리로 둘러싸인 범위에 있는 공을 감지합니다. 이 이미지를 이진화하여 흑백 이미지로 만듭니다.
공을 흰색으로 감지할 수 있지만 배경과 공이 같은 흰색이기 때문에 공만을 감지할 수 없습니다. 여기에서 전후의 프레임 화상으로 배경 차분을 실시하면 이하와 같이 됩니다.
배경의 흰색은 작동하지 않으므로 배경 차이로는 감지되지 않으며 공과 기타 노이즈만 흰색으로 감지됩니다. 이 상태에서 다음과 같은 템플릿 이미지를 2진화한 이미지와 템플릿 매칭을 실시합니다.
이렇게 하면 광도나 배경의 영향을 받지 않고 볼을 검출할 수 있습니다.
소스 코드
소스 코드는 다음과 같습니다.
VIDEOPATH
에 대상 동영상을, TEMPLATEPATH
에 템플릿 이미지를 배치하십시오.main.py
import glob
import re
import cv2
VIDEOPATH = "media/video/video.mp4"
IMAGEPATH = "media/image/"
TEMPLATEPATH = "template.jpeg"
def save_frames(video_path, image_dir):
"""
動画からフレームの画像を抽出
"""
cap = cv2.VideoCapture(video_path)
digit = len(str(int(cap.get(cv2.CAP_PROP_FRAME_COUNT))))
n = 0
while True:
ret, frame = cap.read()
if ret:
cv2.imwrite("{}original/frame_{}.{}".format(IMAGEPATH, n, "jpeg"), frame)
n += 1
else:
return
def do_grayscale(image_path):
"""
画像をグレースケール化
"""
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
save_image(image_path, "gray", gray)
def do_binarization(image_path):
"""
画像を2値化
"""
img = cv2.imread(image_path)
ret, img_thresh = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)
save_image(image_path, "binary", img_thresh)
def do_backgroundsub():
"""
背景差分を行う
"""
img_list = glob.glob(IMAGEPATH + "binary/frame*.jpeg")
num = lambda val: int(re.sub("\D","",val))
sorted(img_list,key=(num))
source = img_list[0]
for path in img_list:
diff = cv2.absdiff(cv2.imread(source),cv2.imread(path))
source = path
save_image(path, "bgsub", diff)
def do_template_matching():
"""
テンプレート画像とフレーム画像でテンプレートマッチングを行う
"""
template_img = cv2.imread(IMAGEPATH + "binary/" + TEMPLATEPATH)
img_list = glob.glob(IMAGEPATH + "bgsub/frame*.jpeg")
num = lambda val: int(re.sub("\D","",val))
sorted(img_list,key=(num))
location_list = []
for path in img_list:
result = cv2.matchTemplate(cv2.imread(path), template_img, cv2.TM_CCOEFF)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(result)
location_list.append(maxLoc)
return location_list
def draw_rectangle(location_list):
"""
マッチング結果を画像に描画する
"""
source = cv2.imread(IMAGEPATH + "original/frame_0.jpeg")
cv2.imwrite(IMAGEPATH + "result.jpeg",source)
source = cv2.imread(IMAGEPATH + "result.jpeg")
for loc in location_list:
lx, ly, rx, ry = loc[0] - 10, loc[1] - 10, loc[0] + 10, loc[1] + 10
img = cv2.rectangle(source, (lx, ly), (rx, ry), (0, 255, 0), 3)
cv2.imwrite(IMAGEPATH + "result.jpeg",img)
def save_image(img_path, dir, img):
"""
画像を保存する
img_path : 画像のパス
dir : ディレクトリ名
img : 画像データ
"""
file_name = img_path.replace("\\","/").split(".")[0].split("/")[-1]
cv2.imwrite("{}{}/{}.{}".format(IMAGEPATH, dir, file_name,"jpeg"), img)
if __name__=="__main__":
# ①動画をフレームごとに分割
save_frames(VIDEOPATH,IMAGEPATH)
# ②テンプレート画像とフレーム画像をグレースケール化
do_grayscale(IMAGEPATH + TEMPLATEPATH)
for path in glob.glob(IMAGEPATH + "original/*.jpeg"):
do_grayscale(path)
# ③テンプレート画像とフレーム画像の2値化
for path in glob.glob(IMAGEPATH + "gray/*.jpeg"):
do_binarization(path)
# ④背景差分を行う
do_backgroundsub()
# ⑤テンプレートマッチングを行う
location_list = do_template_matching()
# ⑥マッチングした座標を投影
draw_rectangle(location_list)
결과
투구 동영상으로 공을 검출해 보았습니다. 일반적으로 검출할 수 있습니다만, 볼의 궤도 이외의 부분도 검출하고 있습니다.
노이즈나 이상치를 수정하는 방법이 있었는데 잊었기 때문에 다시 기억합니다.
요약
Python + OpenCV에서 배경 차이와 템플릿 매칭을 사용하여 야구 공을 추적했습니다.
YOLO
를 사용하면 이미지 안에서 야구공을 검출할 수 있는 것 같아서 이 근처도 시도해보고 싶습니다.
Reference
이 문제에 관하여(Python + OpenCV로 야구 공을 추적), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/t_okkan/items/e08116d989bd9e241052텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)