Medomatto
Medomatto

Reputation: 57

Video crop with automatic specific contour recognition

I need some help with a project. My intention is to crop videos of sonographies with OpenCV and python in order to process them further. The features I am looking for are:

  1. Loop through all available videos in a folder
  2. find the contours and crop
  3. export each video with one fixed size and resolution

Now i am a bit stuck on the contour finding and cropping part. I would like OpenCV to automatically recognize a bounding box around the shape of the sonography, knowing that all videos have the particular conus shape. Besides, it would be great if the non-relevant clutter could be removed. Can you help me? Attached you can find one original frame of the videos and the desired result.

import cv2
import numpy as np

cap = cv2.VideoCapture('video.mjpg')

# (x, y, w, h) = cv2.boundingRect(c)
# cv2.rectangle(frame, (x,y), (x+w, y+h), (0, 255, 0), 20)
# roi = frame[y:y+h, x:x+w]

while True:
    ret, frame = cap.read()
    # (height, width) = frame.shape[:2]
    sky = frame[0:100, 0:200]
    cv2.imshow('Video', sky)

    if cv2.waitKey(1) == 27:
        exit(0)

sample image from a video

desired result

Upvotes: 1

Views: 741

Answers (1)

Shamshirsaz.Navid
Shamshirsaz.Navid

Reputation: 2362

For the first frame of video; you can use this to detect the bounding-box of the image and then you can crop it or whatever you want :)

import sys
import cv2
import numpy as np

# Load our image
dir = sys.path[0]
org = cv2.imread(dir+'/im.png')
im=org.copy()
H,W=im.shape[:2]

# Convert image to grayscale
im=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)

# remove noise
im=cv2.GaussianBlur(im,(21,21),21)
im=cv2.erode(im,np.ones((5,5)))

# remove horizantal line
im=cv2.GaussianBlur(im,(5,0),21)
blr=im.copy()

# make binary image
im=cv2.threshold(im,5,255,cv2.THRESH_BINARY)[1]

# draw black border around image to better detect blobs:
cv2.rectangle(im,(0,0),(W,H),0,thickness=W//25)
bw=im.copy()

# Invert the black and white colors
im=~im

# Find contours and sort them by width
cnts, _ = cv2.findContours(im, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnts.sort(key=lambda x: cv2.boundingRect(x)[2],reverse=True)

# Change the type and channels of image copies
im=cv2.cvtColor(im,cv2.COLOR_GRAY2BGR)
bw=cv2.cvtColor(bw,cv2.COLOR_GRAY2BGR)
blr=cv2.cvtColor(blr,cv2.COLOR_GRAY2BGR)

# Find the second biggest blob
x, y, w, h = cv2.boundingRect(cnts[1])
cv2.rectangle(org, (x, y), (x+w, y+h), (128, 0, 255), 10)
cv2.rectangle(im, (x, y), (x+w, y+h), (128, 255, 0), 10)
print(x,y,w,h)

# Save final result
top=np.hstack((blr,bw))
btm=np.hstack((im,org))
cv2.imwrite(dir+'/img_.png',np.vstack((top,btm)))

enter image description here

Bounding-Box area:

133 25 736 635

Cut and save the final image:

org = cv2.imread(dir+'/im.png')
cv2.imwrite(dir+'/img_.png',org[y:y+h,x:x+w])

enter image description here

Upvotes: 1

Related Questions