Last active
April 16, 2020 09:35
-
-
Save jiristepan/58e6538fd01bf12621e7a58cbefe8103 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import cv2 | |
import sys | |
# input and output folders | |
basedir = "/mnt/c/MEDIA" | |
infolder = "input" | |
outfolder = "output" | |
if (len(sys.argv) != 2): | |
print("Missing input file argument") | |
print("Usage: python3 ./search_red.py $filename") | |
print("Example: python3 ./search_red.py DVI196.MOV") | |
print("\nInput fille should be in %s/%s and the output folder %s/%s should be created" %(basedir,infolder, basedir, outfolder)) | |
quit() | |
infile=sys.argv[1] # file name of file to process | |
inputFileFull= "%s/%s/%s" % (basedir,infolder,infile) | |
outputFileFull= "%s/%s/%s" % (basedir,outfolder,infile) | |
print("Searching red pixels in %s -> %s" %(inputFileFull, outputFileFull)) | |
# open capturing device and check | |
cap = cv2.VideoCapture(inputFileFull) | |
if (cap.isOpened() == False): | |
print("Unable to read video file") | |
# get video stream params | |
frame_width = int(cap.get(3)) | |
frame_height = int(cap.get(4)) | |
# prepare output video file | |
# Define the codec and create VideoWriter object. | |
out = cv2.VideoWriter("/mnt/c/MEDIA/output/%s.avi" % (infile.replace(".","-")),cv2.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width,frame_height)) | |
# configurations - color boundaris | |
# warning - the color code is not RGB, but reverse BGR | |
boundaries = ([00, 00, 123], [88, 88 , 190]) # bottom and top of color space to filter | |
STARTTRESHOLD = 1 # how many red pixels trigger screenshot | |
waitUntilNextFileFrames = 5 #how many frames skip until next screenshot | |
treshold = STARTTRESHOLD #actual treshold | |
nextFileFrame=waitUntilNextFileFrames # actual next frame | |
frames = 0 # frame counter | |
files = 0 # genarated files counter | |
# main loop - frame by frame proceesing | |
while(True): | |
# Capture next frame | |
ret, frame = cap.read() | |
# detect end of file | |
if not ret: | |
break | |
# frame counter | |
frames = frames + 1 | |
############################################## | |
# STEP 1: filter pixels between color limits | |
############################################## | |
# create NumPy arrays from the color boundaries | |
lower = np.array(boundaries[0], dtype = "uint8") | |
upper = np.array(boundaries[1], dtype = "uint8") | |
# create range color mas and apply | |
mask = cv2.inRange(frame, lower, upper) | |
filteredImg = cv2.bitwise_and(frame, frame, mask = mask) | |
#count number of not zero pixels - must be grayscale, countNonZero don't work | |
grayImg = cv2.cvtColor(filteredImg, cv2.COLOR_BGR2GRAY) | |
count = cv2.countNonZero(grayImg) | |
#print status | |
print("frame= %d\tredPixels=%d\tgeneratedFiles=%d" % (frames, count, files)) | |
#make copy before | |
imageForFile=frame.copy() | |
############################################### | |
# STEP 2: Find pixels boundaries for better | |
# visualization | |
############################################### | |
# calculculate countours of non zeropixels | |
ret, threshImg = cv2.threshold(grayImg, 1, 1, 1) | |
im2, contours, hierarchy = cv2.findContours(threshImg, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) | |
if(len(contours) > 1 ): | |
# find the outer rectangle of pixels | |
maxx=0 | |
minx=5000 | |
maxy=0 | |
miny=5000 | |
for contour in contours[1:]: | |
for point in contour: | |
#print(point) | |
x=point[0][0] | |
y=point[0][1] | |
maxx = max(x,maxx) | |
minx = min(x,minx) | |
maxy = max(y,maxy) | |
miny = min(y,miny) | |
# draw countour and boundary info to visible image - makes pixels more visible | |
cv2.rectangle(frame,(minx-10,miny-10),(maxx+10,maxy+10),(0,0,255),2) | |
cv2.drawContours(frame, contours[1:], -1, (0,0,255), 1) | |
# write frame with boundaries to output video file | |
out.write(frame) | |
######################################### | |
# STEP 3: Show frame with potential pixels and boundaries as a smaller video | |
######################################### | |
# show actual image with metadata resized to HD | |
imagePreview=cv2.resize(frame,(1280,720)) | |
cv2.imshow('actualFrame',imagePreview) | |
################################################################## | |
# STEP 4: Save to file if there are more red pixels than treshold | |
################################################################## | |
if count > treshold: | |
# don't save every file | |
if frames >= nextFileFrame: | |
# add rectangle to image - but not pixel contours | |
cv2.rectangle(imageForFile,(minx,miny),(maxx,maxy),(0,255,0),2) | |
# image filename contains information about: source videofile actual frame and number of red pixels | |
jpegFileNameFull = "%s/%s/%s-%d-%d.jpg" % (basedir,outfolder,infile.replace(".","-"),count,frames) | |
print("New suspicious image: %s", (jpegFileNameFull)) | |
cv2.imwrite(jpegFileNameFull,imageForFile) | |
files = files + 1 | |
nextFileFrame=frames+waitUntilNextFileFrames # don't save few next frames | |
treshold=min(count * 1.2 ,100) # increase treshold for a while | |
else: | |
treshold=max(treshold-5, STARTTRESHOLD) # if nothing found lower theshold back to start | |
# wait for user input to break the cycle | |
if cv2.waitKey(1) & 0xFF == ord('q'): | |
break | |
# end of main loop | |
# When everything done, release the capture and output | |
cap.release() | |
out.release() | |
cv2.destroyAllWindows() | |
print("All done. There is %d suspicious images in %s/%s" % (files,basedir,outfolder)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment