MIT-Fishery-App / clipper.py
aus10powell's picture
Upload 32 files
74cd228
raw
history blame
3.51 kB
import cv2
import numpy as np
import yaml
from contour import Contour
class Clipper():
def __init__(self): # TODO: put this in config
self.bg = None
self.seen_fish = False
self.vid_num = 1
self.load_config()
def load_config(self):
with open("config.yaml") as params:
config = yaml.safe_load(params)
self.MAX_CHUNK_SIZE = config.get("DST_VID_MAX_SECS") * config.get("DST_VID_FPS")
k_size = config.get("KERNEL_BLUR_PX")
self.BLUR_KERNEL = np.ones((k_size,k_size),np.uint8)
self.MIN_RAD = config.get("MIN_RADIUS_CONTOUR_PX")
self.cap = cv2.VideoCapture(config.get("SRC_VID_FP"))
self.dst_name = config.get("DST_VID_NAME")
self.dst_ftype = config.get("DST_VID_FILETYPE")
self.dst_vid_fp = config.get("DST_VID_FP")
self.dst_fps = config.get("DST_VID_FPS")
self.show_cnt = config.get("SHOW_CONTOUR")
def clip_vid(self):
""""
Truncates long video files into segments and saves them.
This prevents OutOfMemory exceptions caused by long videos.
"""
running = True
while running is True:
ret, frame = self.cap.read()
if not ret:
print(ret)
running = False
else:
if self.bg is None:
self.bg = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
cnt_list = Clipper.detect_contours(frame, self.bg, self.BLUR_KERNEL, self.MIN_RAD)
if len(cnt_list) > 0:
self.write_vid(cnt_list)
def write_vid(self, cnt_list):
fourcc = cv2.VideoWriter_fourcc('F', 'M', 'P', '4')
video = cv2.VideoWriter(self.dst_vid_fp + self.dst_name + str(self.vid_num) + self.dst_ftype, fourcc, self.dst_fps, (int(self.cap.get(3)), int(self.cap.get(4))))
frame_cnt = 0
while True:
ret, frame = self.cap.read()
if self.show_cnt:
for cnt in cnt_list:
frame = cv2.circle(frame, (cnt.x,cnt.y), cnt.rad, (0, 0, 255), 1)
video.write(frame)
frame_cnt += 1
cnt_list = Clipper.detect_contours(frame, self.bg, self.BLUR_KERNEL, self.MIN_RAD)
if (len(cnt_list) <= 0) or (frame_cnt > self.MAX_CHUNK_SIZE):
video.release()
self.vid_num += 1
break
@staticmethod
def detect_contours(frame, bg, kernel, min_rad):
# Use HSV colorspace to minimize lighting variance
img = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# Take absolute value of difference and blur to denoise
difference = img - bg
greyscale = cv2.cvtColor(difference, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(greyscale, 150, 255, cv2.THRESH_BINARY)
erosion = cv2.erode(thresh, kernel, iterations = 1)
cnt_list = []
# Find contours > 15 px in diameter
contours, hierarchy = cv2.findContours(image=erosion, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)
for cnt in contours:
(x,y), radius = cv2.minEnclosingCircle(cnt)
if int(radius) > min_rad: # TODO Figure out smallest size of herring
cnt_list.append(Contour(int(x),int(y),int(radius)))
return cnt_list
if __name__ == "__main__":
# Script below to enable running pure inference from command line
c = Clipper()
c.clip_vid()