import cv2
import numpy as np
#Init camera
cap = cv2.VideoCapture(0)
#Face Detection using haarcascade File
face_cascade = cv2.CascadeClassifier('Anaconda3\Lib\site-packages\cv2\data\haarcascade_frontalface_alt.xml')
skip = 0
face_data = []
#dataset_path = ('./Face Recognition Data')
while True:
ret,frame = cap.read()
if ret == False:
continue
faces = face_cascade.detectMultiScale(frame,1.3,5)
#The next line of code is written to only store the largest face in the window frame
faces = sorted(faces,key = lambda f: f[2]*f[3])
#start sorting from the last face since the last face is the largest in terms of area(w*h)
for face in faces[-1:] :
x,y,w,h = face
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,255),2)
#extract the required face or the region of the interest
#Refers to adding an extra 10 pixels on all the sides of the required extracted face
offset = 10
#By default face slicing is done in (y,x) manner
face_section = frame[y-offset:y+h+offset,x-offset:x+w+offset]
face_section = cv2.resize(face_section,(100,100))
if skip%10==0 : #Store every 10th frame
face_data.append(face_section)
print(len(face_data)) #number of faces captured so far
cv2.imshow("Video Frame",frame)
cv2.imshow("Face section frame",face_section)
key_pressed = cv2.waitKey(1) & 0xFF
if key_pressed == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
After running the program, it says that face_section variable is not defined.
Please help
You have more than one face_section. If you need them outside of your for loop you may do like this:
face_section_list = [] # Define a new empty list!
#start sorting from the last face since the last face is the largest in terms of area(w*h)
for face in faces[-1:] :
x,y,w,h = face
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,255),2)
#extract the required face or the region of the interest
#Refers to adding an extra 10 pixels on all the sides of the required extracted face
offset = 10
#By default face slicing is done in (y,x) manner
face_section = frame[y-offset:y+h+offset,x-offset:x+w+offset]
face_section = cv2.resize(face_section,(100,100))
face_section_list.append(face_section) # Append EVERY face!
if skip%10==0 : #Store every 10th frame
face_data.append(face_section)
print(len(face_data)) #number of faces captured so far
And then outside, print every face in order (or do whatever you need to do):
for im in face_section_list:
cv2.imshow("Face section frame",im)
cv2.waitKey(0) # Zero means "wait until a key is pressed"
I've wrote a lot of code for face detection and recognition that you may find helpful, have a look.
Related
i was working with face mesh module of opencv to detect my face
when i try to run it on my code editor it show
"landmarks = landmark_points(1).landmark" this list as not callable
import cv2
import mediapipe as mp
from cv2 import _registerMatType
cam = cv2.VideoCapture(0)
face_mesh = mp.solutions.face_mesh.FaceMesh()
while True:
_, frame = cam.read()
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
#to get face detected
output = face_mesh.process(rgb_frame)
landmark_points = output.multi_face_landmarks
#to get coordinates of face
if landmark_points:
landmarks = landmark_points(1).landmark
for landmark in landmarks:
x = landmark.x
y = landmark.y
print(x, y)
#frame display
cv2.imshow('face detection', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cam.release
cv2.destroyAllWindows()
the code work properly if we replace the coordinate section with "print(landmark_points)"
but i can not use the then result for my purpose, as i want it in (x,y) format
tried some sources but could not understand problem.
can some one provide solution with expanation?
landmark_points is a list. landmark_points(1) attempts to "call" it like a function. Did you mean landmark_points[1]? That accesses an element in a list with index 1.
Note that landmark_points[1] is a second element, you probably want landmark_points[0] (first element)
I am working on a project for camera tampering. I have the code for tamper detection for a static camera. Tampering means blocking or defocussing the camera. I want to modify it for a moving camera or rotating camera so that it takes all the frames from the background and then compare it with new frames using the same background subtractor method.
I have tried but unable to figure out how to use the list of frames to compare the captured frame from other ones.
import numpy as np
import cv2
from playsound import playsound
import time
#cap = cv2.VideoCapture('http://192.168.43.1:8080/video') #Opening of IP camera just enter the ip address
cap = cv2.VideoCapture(0)
fgbg = cv2.createBackgroundSubtractorMOG2() #generating a foreground mask
frame_list = [] #creating the list of frame
##################################################################
while(True):
ret, frame = cap.read()
if ret == True:
if frame not in frame_list:
frame_list.append(frame) #This list contain all the frames
###################################################################
#ret, frame = cap.read() #to get the initial frame
#fgmask = fgbg.apply(frame) #to save the initial frame
kernel = np.ones((5,5), np.uint8) #creating a matrix of (5, 5) consisting of 1
while(True):
ret, frame = cap.read() #reading all the frames
if ret == True:
a = 0
bounding_rect = [] # An empty list where will furthur input the contours
fgmask = fgbg.apply(frame) #Applying the changes of the backgroud to the foreground mask
fgmask= cv2.erode(fgmask, kernel, iterations=5)
fgmask = cv2.dilate(fgmask, kernel, iterations = 5) #Erosion and Dilation is done to detect even the blur objects better
cv2.imshow('frame',frame) #Showing the frame.
contours,_ = cv2.findContours(fgmask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) #The mode RETR_TREE together with the CHAIN APPROX_SIMPLE returns only the endpoints required to draw contour
for i in range(0,len(contours)):
bounding_rect.append(cv2.boundingRect(contours[i])) #cv2.bounding rectangle gives the coordinates of bounding rectangle and then we will input these coordinates to the list we made
for i in range(0,len(contours)):
if bounding_rect[i][2] >=40 or bounding_rect[i][3] >= 40: #setting the threshold for the width and height if the contour
a = a+(bounding_rect[i][2])*bounding_rect[i][3] #updating the area of contour
if(a >=int(frame.shape[0])*int(frame.shape[1])/3): #It is basically the comparison of the change in area of the background, so if there is a certain change in area it will detect the tampering
cv2.putText(frame,"TAMPERING DETECTED",(5,30),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,255),2)
#playsound('warning.mp3') #put the address of the warning tune in the playsound object and uncomment it
cv2.imshow('frame',frame) #showing the final frame
if cv2.waitKey(30) & 0xff== ord('q'): #To close the camera press q
break
else : break
cap.release()
cv2.destroyAllWindows()
In my opinion, I don't think background subtraction is a good solution to your problem, your methods is mainly used to detect moving object by subtracting background. This method most often used in static camera but for moving camera, intensity variation or texture change may also need to take account.
I've a scenario where only trucks will pass a toll gate of which I want to capture the number plate only when the truck has halted (to get a good quality image to run OCR on). The OCR solution is built but capturing a frame every time a truck comes to a halt seems to be tricky to me.
Can you help me with the approach or a similar working code to achieve the same using Python 3.6+ and OpenCV. I'm not willing to run any explicit model to detect motion or something, just a simple background subtraction would do, in order to avoid overhead time.
Sample image frame from the video: click here.
Here is the code I'm currently working on, it checks if the background subtraction between two respective frames is more than 10% threshold, then it captures the frame. But, I've to do just the opposite, i.e, if background subtraction is zero, then capture the frame, more logic needs to be added here, like, after capturing a frame, we've to skip all following static frames which are true positive until the the next truck arrives and comes to a halt.
The code:
x_0 = 720
x_1 = 870
y_0 = 190
y_1 = 360
fgbg = cv2.createBackgroundSubtractorMOG2()
cap = cv2.VideoCapture(r"C:\\Users\\aa\\file.asf")
i=0
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame = cv2.GaussianBlur(frame, (21, 21), 0)
fgmask = fgbg.apply(frame)
fgmask_crop= fgmask[y_0:y_1, x_0:x_1]
frame_crop = frame[y_0:y_1, x_0:x_1]
#out_video.write(frame_crop)
cv2.imshow("crop", fgmask_crop)
fg = cv2.copyTo(frame,fgmask)
bg=cv2.copyTo(frame,cv2.bitwise_not(fgmask))
pixels = cv2.countNonZero(fgmask_crop)
image_area = frame_crop.shape[0] * frame_crop.shape[1]
area_ratio = (pixels / image_area) * 100
if area_ratio>10:
i=i+1
print(i)
target= 'C:\\Users\\aa\\op'
fileName = ("res%d.png" % (i))
path_nm = os.path.join(target, fileName)
cv2.imwrite(path_nm,frame_crop)
key = cv2.waitKey(25)
if key == ord('q'):
break
else:
break
cv2.destroyAllWindows()
#out.release()
cap.release()
Any help shall be highly acknowledged.
So the popular approach to lane detection using computer vision is to perform these 5 steps:
Convert the image to grayscale, smooth the image by gaussian
function
Use canny edge function to detect edges (obviously right? )
Mark the region of interest ROI
Use hough transform fucntion to detect straight lines and have line function to draw them.
That's what my approach.
But the point here is we usually need to manually select the ROI. In most case when apply to dash camera on a car, it's ok since the view does not change much.
But my situation is different, I want to detect road lanes based on traffic surveillance cameras, and of course there are many of them. Each camera has its own view, so I think that there must be a way to automatically separate the road and non-road areas.
My question is how to detect the ROI automatically?
My idea here is that the road area will have lots of pixel movements and the non-road area will not. From that idea we could automatically detect the ROI.
I have manage to use opencv to extract the background (background subtracted) from this video (https://youtu.be/bv3NEzjb5sU) using openCV and subtractBackgroundMOG2 function.
The code about canny edge and hough transform is basically ok after we have the ROI. This below is the code to train and extract the background. I though we could modify it to give the region mask or something that can use as ROI for later steps.
Thank you.
import cv2
from pathlib import Path
def bg_train(video_source, number_of_run, number_of_frames):
cap = cv2.VideoCapture(video_source)
fgbg = cv2.createBackgroundSubtractorMOG2(detectShadows=True)
frame_number = -1
default_background = Path("default_background.png")
# the number of loop that will run to create a better background
i = 0
# check the file if it's already exist
if default_background.is_file():
i = 1
default_background = "default_background.png"
else:
default_background = None
i = 0
while i < number_of_run:
# Capture next frame and show in window
ret, frame = cap.read()
if not ret:
print("frame capture failed or not :)")
break
cv2.imshow("training_original", frame)
# subtract foreground and show in new window
background_read = cv2.imread(default_background)
fg = fgbg.apply(frame, background_read, -1)
fg_mask = filter_mask(fg)
cv2.imshow('Training_FG', fg_mask)
# subtract background and show in new window
bg = fgbg.getBackgroundImage(fg_mask)
cv2.imshow('Training_background', bg)
print(i, frame_number, bg.shape[0], bg.shape[1], bg.shape[2])
# Counting frame and save the final background after training
frame_number += 1
if frame_number == number_of_frames and i < number_of_run - 1:
i += 1
cv2.imwrite("default_background.png", bg)
cap.release()
cv2.destroyAllWindows()
cap = cv2.VideoCapture(video_source)
frame_number = -1
elif frame_number == number_of_frames and i == number_of_run - 1:
i += 1
cv2.imwrite("background_final.png", bg)
cv2.imshow("final background", bg)
return 1, bg
k = cv2.waitKey(1) & 0xff
if k == 27:
print("exit by user...")
return 0, None
cap.release()
cv2.destroyAllWindows()
def main():
video_source = "highway-30s.mp4"
check, background_after = bg_train(video_source, 2, 500)
if check == 0:
return 0
elif check == 1:
cv2.imshow("the background, press ESC to close window", background_after)
c = cv2.waitKey(0)
if c == 27:
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
You could train the algorithm to pick the ROI, over an initial amount of time, by tracking movement in the viewport over a series of frames.
Filter out movements and create lines/vectors representing their direction. Once you have enough of these samples you can figure out the best ROI by using a bounding box which encapsulates these vectors.
I am using a microscope to observe the motion of small 4 micron beads. I have a video of the beads moving and I would like to process the video to extract the bead locations as a function of time to get a mathematical model of their motion.
I am currently using opencv and programming in python
My code was importing a video from file, thresholding the image then applying a HoughCircles transform to find the spherical beads.
import numpy as np
import cv2
def nothing(x):
pass
cap = cv2.VideoCapture('testvideo.mp4')
cv2.namedWindow('trackbar')
cv2.createTrackbar('Param1','trackbar',40,255,nothing)
cv2.createTrackbar('Param2','trackbar',10,255,nothing)
cv2.createTrackbar('MaxRadius','trackbar',18,255,nothing)
while(cap.isOpened()):
e1 = cv2.getTickCount()
ret, frame = cap.read()
#get grayscale image for HoughCircles
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
p1 = cv2.getTrackbarPos('Param1','trackbar')
p2 = cv2.getTrackbarPos('Param2','trackbar')
rMax = cv2.getTrackbarPos('MaxRadius','trackbar')
#Threshold grayscale image
ret,th1 = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
#Find circles in image and store locations to circles list
circles = cv2.HoughCircles(th1, cv2.cv.CV_HOUGH_GRADIENT, 1, 10,
param1=p1, param2=p2,minRadius=0,
maxRadius=rMax)
#Hack for fixing the list if it is empty so program wont crash
if circles == None:
circles = [[[0,0,0.000],[0,0,0.000]]]
#convert circles list to integer list
circles = np.uint16(np.around(circles))
#store points to a file
datafile = file('datafile.txt', 'a')
np.savetxt(datafile, circles[0], fmt ='%i',delimiter=',', newline = ',')
datafile.write('\n')
datafile.close()
for i in circles[0,:]:
# draw the outer circle
cv2.circle(frame,(i[0],i[1]),i[2],(0,255,0),2)
# draw the center of the circle
cv2.circle(frame,(i[0],i[1]),2,(0,0,255),3)
cv2.imshow('detected circles',frame)
cv2.imshow('threshold video',th1)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
e2 = cv2.getTickCount()
time = (e2 - e1)/ cv2.getTickFrequency()
print time
cap.release()
cv2.destroyAllWindows()
Here is a sample frame from the video I am using for detecting the beads.
http://imgur.com/bVZbH3c
Here is an example of the single frame tracking that I did with the previous algorithm
http://imgur.com/4VWJI2F
I don't need to detect every single bead. Just an aggregate would be fine.
The beads are spherical and should look the same, so is there a library that I can use to integrate the bead image over the entire image and see where the points are most correlated in the image? Sometimes the beads are out of focus and that's why the current program I have keeps bouncing around and giving me false positives for the beads.
I eventually need this process to happen realtime so if possible it would be nice to have the algorithm be as efficient as possible.
If anyone knows a good approach to this type of problem it would be appreciated.