Is there any way i can make my own train set for face recognition in python ? To be more specific i want to make a train set like an AT&T Face database. I want my camera to take 20 images of each person(30 max) and store it in the separate folders by the name of each person.
import cv2, sys, numpy, os
size = 4
fn_haar = 'haarcascade_frontalface_default.xml'
fn_dir = 'att_faces'
fn_name = sys.argv[1]
path = os.path.join(fn_dir, fn_name)
if not os.path.isdir(path):
os.mkdir(path)
(im_width, im_height) = (112, 92)
haar_cascade = cv2.CascadeClassifier(fn_haar)
webcam = cv2.VideoCapture(0)
# The program loops until it has 20 images of the face.
count = 0
while count < 20:
(rval, im) = webcam.read()
im = cv2.flip(im, 1, 0)
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
mini = cv2.resize(gray, (gray.shape[1] / size, gray.shape[0] / size))
faces = haar_cascade.detectMultiScale(mini)
faces = sorted(faces, key=lambda x: x[3])
if faces:
face_i = faces[0]
(x, y, w, h) = [v * size for v in face_i]
face = gray[y:y + h, x:x + w]
face_resize = cv2.resize(face, (im_width, im_height))
pin=sorted([int(n[:n.find('.')]) for n in os.listdir(path)
if n[0]!='.' ]+[0])[-1] + 1
cv2.imwrite('%s/%s.png' % (path, pin), face_resize)
cv2.rectangle(im, (x, y), (x + w, y + h), (0, 255, 0), 3)
cv2.putText(im, fn_name, (x - 10, y - 10), cv2.FONT_HERSHEY_PLAIN,
1,(0, 255, 0))
count += 1
cv2.imshow('OpenCV', im)
key = cv2.waitKey(10)
if key == 27:
break
For this, you just need to provide a particular path to save all the image with (.png) or (.bmp) or (.jpg) extension in a sorted manner.
# train.py
import cv2, sys, numpy, os
size = 4
fn_haar = 'haarcascade_frontalface_default.xml'
fn_dir = 'face_data'
fn_name = sys.argv[0]
path = os.path.join(fn_dir, fn_name)
(im_width, im_height) = (112, 92)
haar_cascade = cv2.CascadeClassifier(fn_haar)
webcam = cv2.VideoCapture(0)
# Generate name for image file
pin=sorted([int(n[:n.find('.')]) for n in os.listdir(path)
if n[0]!='.' ]+[0])[-1] + 1
# Beginning message
print("\n\033[94mThe program will save 20 samples. \
Move your head around to increase while it runs.\033[0m\n")
# The program loops until it has 20 images of the face.
count = 0
pause = 0
count_max = 20
while count < count_max:
# Loop until the camera is working
rval = False
while(not rval):
# Put the image from the webcam into 'frame'
(rval, frame) = webcam.read()
if(not rval):
print("Failed to open webcam. Trying again...")
# Get image size
height, width, channels = frame.shape
# Flip frame
frame = cv2.flip(frame, 1, 0)
# Convert to grayscale
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Scale down for speed
mini = cv2.resize(gray, (int(gray.shape[1] / size), int(gray.shape[0] / size)))
# Detect faces
faces = haar_cascade.detectMultiScale(mini)
# We only consider largest face
faces = sorted(faces, key=lambda x: x[3])
if faces:
face_i = faces[0]
(x, y, w, h) = [v * size for v in face_i]
face = gray[y:y + h, x:x + w]
face_resize = cv2.resize(face, (im_width, im_height))
# Draw rectangle and write name
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
cv2.putText(frame, fn_name, (x - 10, y - 10), cv2.FONT_HERSHEY_PLAIN,
1,(0, 255, 0))
# Remove false positives
if(w * 6 < width or h * 6 < height):
print("Face too small")
else:
# To create diversity, only save every fith detected image
if(pause == 0):
print("Saving training sample "+str(count+1)+"/"+str(count_max))
# Save image file
cv2.imwrite('%s/%s.png' % (path, pin), face_resize)
pin += 1
count += 1
pause = 1
if(pause > 0):
pause = (pause + 1) % 5
cv2.imshow('OpenCV', frame)
key = cv2.waitKey(10)
if key == 27:
break
This code will help you to get the cropped images from the webcam and store them in a directory name as face_data for training purpose.
In case, you don't want to train your dataset from webcam, you can simply do one thing:
that just create a directory and create 5-6 sub-directory in it as in Happy, Sad, Angry, Neutral, Calm, etc.
Download the images and put them in corresponding folders for training purpose, now follow this code.
## This program first ensures if the face of a person exists in the given image or
not then if it exists, it crops
## the image of the face and saves to the given directory.
## Importing Modules
import cv2
import os
directory = "C:\\Users\\hp"
## directory where the images to be saved:
f_directory = "C:\\Users\\hp\\face_data/"
def facecrop(image):
## Crops the face of a person from an image!
## OpenCV XML FILE for Frontal Facial Detection using HAAR CASCADES.
facedata=
"C:\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_default.xml"
cascade = cv2.CascadeClassifier(facedata)
## Reading the given Image with OpenCV
img = cv2.imread(image)
try:
minisize = (img.shape[1],img.shape[0])
miniframe = cv2.resize(img, minisize)
faces = cascade.detectMultiScale(miniframe)
for f in faces:
x, y, w, h = [ v for v in f ]
cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
sub_face = img[y:y+h, x:x+w]
f_name = image.split('/')
f_name = f_name[-1]
## Change here the Desired directory.
cv2.imwrite(f_directory + f_name, sub_face)
print ("Writing: " + image)
except:
pass
if __name__ == '__main__':
images = os.listdir(directory)
i = 0
for img in images:
file = directory + img
print (i)
facecrop(file)
i += 1
Related
I have a face recognition code(Entire code given at the end) that works perfectly fine with the existing dataset.
But I wanted it to also add new faces into the dataset(Enrollments), after asking for a user input for the name of the new person in the frame [like this: new_name = print(Who is this?)]. So then I could create a new folder by the entered name, and store the face inside the frame. This is what I did:
new_name = input("Who is this?")
path_2 = os.path.join('Images',new_name)
os.mkdir(path_2)
print("Directory '% s' created" % new_name)
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (0,0,255),
thickness = 2)
cv2.putText(frame, new_name, (x, y), cv2.FONT_HERSHEY_SIMPLEX,
0.75, (0, 255, 0), 2)
sub_face = frame[y:y+h, x:x+w]
FaceFileName = new_name + str(y+x) + ".jpg"
cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
cv2.imshow("Frame",frame)
#if cv2.waitKey(1) & 0xFF == ord('q'):
# break
This worked fine with new people. But now I had to do something for unrecognized faces of known people.
In this case, we would already have a folder by the entered name. We must append the image into the existing folder by the entered name.
So for this I tried the below code: (Did not work)
else: # To store the unknown new face with name
new_name = input("Who is this?")
# If the new_name entered already exists as a folder
if os.path.isfile(new_name):
print(new_name,"folder already exists")
frame = imutils.resize(frame, width = 400)
rects = detector.detectMultiScale(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY),
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30))
FaceFileName = new_name + str(y+x) + ".jpg"
for (x, y, w, h) in rects:
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Frame",frame)
key = cv2.waitKey(1) & 0xFF
if key == ord("k"):
p = os.path.join([new_name,FaceFileName.format(str(total).zfill(5))])
# cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
cv2.imwrite(p, orig)
total += 1
print("Image saved")
elif key == ord("q"):
break
# If the new_name does not exist as a folder new folder has to be created
else:
path_2 = os.path.join('Images',new_name)
os.mkdir(path_2)
print("Directory '% s' created" % new_name)
frame = imutils.resize(frame, width = 400)
rects = detector.detectMultiScale(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY),
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30))
FaceFileName = new_name + str(y+x) + ".jpg"
for (x, y, w, h) in rects:
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Frame",frame)
key = cv2.waitKey(1) & 0xFF
if key == ord("k"):
p = os.path.join([path_2,FaceFileName.format(str(total).zfill(5))])
# cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
cv2.imwrite(p, orig)
total += 1
print("Image saved")
I am getting the error:
Who is this?Vishwesh
Traceback (most recent call last):
File "C:\Users\Vishw\databs.py", line 117, in <module>
os.mkdir(path_2)
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'Images\\Vishwesh'
[ WARN:0] global C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-sgoydvi3\opencv\modules\videoio\src\cap_msmf.cpp (438) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callback
Complete code is given below. Let me know what is wrong with the code. Kindly help!
Note: I included the above codes under the # Face recognition on LIVE WEBCAM FEED section and as else statement for the "if True in matches:"
Here is my entire code:
# Extracting features from face
from imutils import paths
import face_recognition
import pickle
import cv2
import os
#Get paths of each file in folder named Images
#Images here contains my data(folders of various persons)
imagePaths = list(paths.list_images('Images'))
knownEncodings = []
knownNames = []
# loop over the image paths
for (i, imagePath) in enumerate(imagePaths):
# extract the person name from the image path
name = imagePath.split(os.path.sep)[-2]
# load the input image and convert it from BGR (OpenCV ordering)
# to dlib ordering (RGB)
image = cv2.imread(imagePath)
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
#Use Face_recognition to locate faces
boxes = face_recognition.face_locations(rgb,model='hog')
# compute the facial embedding for the face
encodings = face_recognition.face_encodings(rgb, boxes)
# loop over the encodings
for encoding in encodings:
knownEncodings.append(encoding)
knownNames.append(name)
#save emcodings along with their names in dictionary data
data = {"encodings": knownEncodings, "names": knownNames}
#use pickle to save data into a file for later use
f = open("face_enc", "wb")
f.write(pickle.dumps(data))
f.close()
# Face recognition on LIVE WEBCAM FEED
import face_recognition
import pickle
import cv2
import os
#find path of xml file containing haarcascade file
cascPathface = os.path.dirname(
cv2.__file__) + "/data/haarcascade_frontalface_default.xml"
# load the harcaascade in the cascade classifier
faceCascade = cv2.CascadeClassifier(cascPathface)
# load the known faces and embeddings saved in last file
data = pickle.loads(open('face_enc', "rb").read())
print("Streaming started")
video_capture = cv2.VideoCapture(0)
# loop over frames from the video file stream
while True:
# grab the frame from the threaded video stream
ret, frame = video_capture.read()
orig = frame.copy()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray,
scaleFactor=1.05,
minNeighbors=3,
minSize=(60, 60),
flags=cv2.CASCADE_SCALE_IMAGE)
# convert the input frame from BGR to RGB
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# the facial embeddings for face in input
encodings = face_recognition.face_encodings(rgb)
names = []
# loop over the facial embeddings incase
# we have multiple embeddings for multiple fcaes
for encoding in encodings:
#Compare encodings with encodings in data["encodings"]
#Matches contain array with boolean values and True for the embeddings it matches closely
#and False for rest
matches = face_recognition.compare_faces(data["encodings"],encoding)
#set name =unknown if no encoding matches
name = "Unknown"
# check to see if we have found a match
if True in matches:
# Find positions at which we get True and store them
matchedIdxs = [i for (i, b) in enumerate(matches) if b]
counts = {}
# loop over the matched indexes and maintain a count for
# each recognized face face
for i in matchedIdxs:
#Check the names at respective indexes we stored in matchedIdxs
name = data["names"][i]
#increase count for the name we got
counts[name] = counts.get(name, 0) + 1
#set name which has highest count
name = max(counts, key=counts.get)
else: # To store the unknown new face with name
new_name = input("Who is this?")
# If the new_name entered already exists as a folder
if os.path.isfile(new_name):
print(new_name,"folder already exists")
frame = imutils.resize(frame, width = 400)
rects = detector.detectMultiScale(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY),
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30))
FaceFileName = new_name + str(y+x) + ".jpg"
for (x, y, w, h) in rects:
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Frame",frame)
key = cv2.waitKey(1) & 0xFF
if key == ord("k"):
p = os.path.join([new_name,FaceFileName.format(str(total).zfill(5))])
# cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
cv2.imwrite(p, orig)
total += 1
print("Image saved")
elif key == ord("q"):
break
# If the new_name does not exist as a folder new folder has to be created
else:
path_2 = os.path.join('Images',new_name)
os.mkdir(path_2)
print("Directory '% s' created" % new_name)
frame = imutils.resize(frame, width = 400)
rects = detector.detectMultiScale(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY),
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30))
FaceFileName = new_name + str(y+x) + ".jpg"
for (x, y, w, h) in rects:
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Frame",frame)
key = cv2.waitKey(1) & 0xFF
if key == ord("k"):
p = os.path.join([path_2,FaceFileName.format(str(total).zfill(5))])
# cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
cv2.imwrite(p, orig)
total += 1
print("Image saved")
# update the list of names
names.append(name)
# loop over the recognized faces
for ((x, y, w, h), name) in zip(faces, names):
# rescale the face coordinates
# draw the predicted face name on the image
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(frame, name, (x, y), cv2.FONT_HERSHEY_SIMPLEX,
0.75, (0, 255, 0), 2)
cv2.imshow("Frame", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
cv2.destroyAllWindows()
So, your issue is rather related to file operations then to face recognition...
Try to check if folder alreday exists before trying to create it:
path_2 = os.path.join('Images',new_name)
if not os.path.exists(path_2):
os.mkdir(path_2)
Using the idea given by #Bohdan:
else: # To store the unknown new face with name
new_name = input("Who is this?")
path_2 = os.path.join('Images',new_name)
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (0,0,255),
thickness = 2)
cv2.putText(frame, new_name, (x, y), cv2.FONT_HERSHEY_SIMPLEX,
0.75, (0, 255, 0), 2)
sub_face = frame[y:y+h, x:x+w]
FaceFileName = new_name + str(y+x) + ".jpg"
if not os.path.exists(path_2):
os.mkdir(path_2)
print("Directory '% s' created" % new_name)
cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
# To store unrecognised faces of known people
else:
cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
Code works perfectly fine!
I am making a object detection project.
I have my code. And I have written it by following a tutorial. In the tutorial, the guy drew a rectangle in opencv for every single object which is detected.
But I want to change the rectangle to triangle or Arrow.
let me explain with code===>
In my function, I detect objects.
And here I draw rectangle for detected objects==>
cv2.rectangle(img, (x, y), (x+w,y+h), (255, 0 , 255), 2)
But I want to change this rectangle to a triangle.(And I want to set position of triangle to above of object.
Just like in these images:::
This is the object detection with triangle
[![enter image description here][1]][1]
This is the thing that what I want to make instead of rectangle:::
[![enter image description here][2]][2]
How Can I make a triangle/arrow with positions of my detected objects?
All of my code is here==>
from os.path import sep
import cv2 as cv2
import numpy as np
import json
# Camera feed
cap_cam = cv2.VideoCapture(0)
ret, frame_cam = cap_cam.read()
hey = 0
print(cv2. __version__)
whT = 320
confThreshold =0.5
nmsThreshold= 0.2
classesFile = "coco.names"
classNames = []
with open(classesFile, 'rt') as f:
classNames = f.read().rstrip('\n').split('\n')
print(classNames)
## Model Files
modelConfiguration = "custom-yolov4-tiny-detector.cfg"
modelWeights = "custom-yolov4-tiny-detector_last.weights"
net = cv2.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
def findObjects(outputs,img):
global hey
global previousHey
hT, wT, cT = img.shape
bbox = []
classIds = []
confs = []
for output in outputs:
for det in output:
scores = det[5:]
classId = np.argmax(scores)
confidence = scores[classId]
if confidence > confThreshold:
w,h = int(det[2]*wT) , int(det[3]*hT)
x,y = int((det[0]*wT)-w/2) , int((det[1]*hT)-h/2)
bbox.append([x,y,w,h])
classIds.append(classId)
confs.append(float(confidence))
global indicates
indices = cv2.dnn.NMSBoxes(bbox, confs, confThreshold, nmsThreshold)
hey = 0
for i in indices:
i = i[0]
box = bbox[i]
x, y, w, h = box[0], box[1], box[2], box[3]
# print(x,y,w,h)
cv2.rectangle(img, (x, y), (x+w,y+h), (255, 0 , 255), 2)
#cv2.line(img, (350,400), (x, y), (255,0,0), 4)
#cv2.line(img, (400,400), (x + 50 , y), (255,0,0), 4)
#cv.putText(img,f'{classNames[classIds[i]].upper()} {int(confs[i]*100)}%',
#(x, y-10), cv.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 255), 2)
print('success')
hey = 1
video_frame_counter = 0
while cap_cam.isOpened():
img = cv2.imread('photos' + sep + 'lutfen.jpg')
#BURADA OK VİDEOSU OYNATILACAK
#if not decetiona diye dene yarın.
blob = cv2.dnn.blobFromImage(img, 1 / 255, (whT, whT), [0, 0, 0], 1, crop=False)
net.setInput(blob)
layersNames = net.getLayerNames()
outputNames = [(layersNames[i[0] - 1]) for i in net.getUnconnectedOutLayers()]
outputs = net.forward(outputNames)
findObjects(outputs,img)
cv2.imshow('Image', img)
# Video feed
if hey == 1:
filename = 'photos' + sep + 'Baslksz-3.mp4'
cap_vid = cv2.VideoCapture(filename)
if hey == 0:
filename = 'photos' + sep + 'vid2.mp4'
cap_vid = cv2.VideoCapture(filename)
print(hey)
ret, frame_vid = cap_vid.read()
#cap_cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
#cap_cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
# Resize the camera frame to the size of the video
height = int(cap_vid.get(cv2.CAP_PROP_FRAME_HEIGHT))
width = int(cap_vid.get(cv2.CAP_PROP_FRAME_WIDTH))
# Capture the next frame from camera
ret, frame_cam = cap_cam.read()
video_frame_counter += 1
if video_frame_counter == cap_vid.get(cv2.CAP_PROP_FRAME_COUNT):
video_frame_counter = 0
cap_vid.set(cv2.CAP_PROP_POS_FRAMES, 0)
frame_cam = cv2.resize(frame_cam, (width, height), interpolation = cv2.INTER_AREA)
#ret = cap_vid.set(cv2.CAP_PROP_POS_MSEC, time_passed)
ret, frame_vid = cap_vid.read()
if not ret:
print('Cannot read from video stream')
break
# Blend the two images and show the result
tr = 0.4 # transparency between 0-1, show camera if 0
frame = ((1-tr) * frame_cam.astype(np.float) + tr * frame_vid.astype(np.float)).astype(np.uint8)
cv2.imshow('Transparent result', frame)
if cv2.waitKey(1) == 27: # ESC is pressed
break
cap_cam.release()
cap_vid.release()
cv2.destroyAllWindows()
The easy way
You can use the cv.arrowedLine() function that will draw something similar to what you want. For example, to draw a red arrow above your rectangle:
center_x = x + w//2
cv2.arrowedLine(img, (center_x, y-50), (center_x, y-5), (0,0,255), 2, 8, 0, 0.5)
which should give a result similar to the image below. Take a look at the OpenCV documentation for the description of the parameters of the function. You can change its size, thickness, color, etc.
Custom arrow shape
If you want more control over the shape of your arrow, you can define a contour (vertex by vertex) and use cv.drawContours() to render it. For example:
# define the arrow shape
shape = np.array([[[0,0],[-25,-25],[-10,-25],[-10,-50],
[10,-50],[10,-25],[25,-25]]])
# move it to the desired position
cx = x + w // 2
cy = y - 5
shape[:,:,0] += cx
shape[:,:,1] += cy
# draw it
cv2.drawContours(img, shape, -1, (0, 255, 0), -1)
This snippet will give you the image below. You can adjust the shape by altering the vertices in the shape array, or look at the documentation to change the way OpenCV draws it.
I have a code to detect and identify the car number plate and convert the image into text using tesseract.
I am using openCV to localise the number plate.
The problem that I am facing is that tesseract is not accurately identifying the number. Is there any way I can improve the tesseract performance?
My code (which I downloaded from Internet) is:
import numpy as np
import cv2
# from copy import deepcopy
from PIL import Image
import pytesseract as tess
# plate = 0
def preprocess(img):
# print ('preprocessing image')
# cv2.imshow("Input", img)
imgBlurred = cv2.GaussianBlur(img, (5, 5), 0)
gray = cv2.cvtColor(imgBlurred, cv2.COLOR_BGR2GRAY)
sobelx = cv2.Sobel(gray, cv2.CV_8U, 1, 0, ksize=3)
cv2.imshow("Sobel",sobelx)
cv2.waitKey(0)
ret2, threshold_img = cv2.threshold(sobelx, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imshow("Threshold",threshold_img)
cv2.waitKey(0)
return threshold_img
def cleanPlate(plate):
# print ("CLEANING PLATE. . .")
gray = cv2.cvtColor(plate, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
thresh= cv2.dilate(gray, kernel, iterations=1)
_, thresh = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
im1, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
if contours:
areas = [cv2.contourArea(c) for c in contours]
max_index = np.argmax(areas)
max_cnt = contours[max_index]
max_cntArea = areas[max_index]
x, y, w, h = cv2.boundingRect(max_cnt)
if not ratioCheck(max_cntArea, w, h):
return plate, None
cleaned_final = thresh[y:y + h, x:x + w]
# cv2.imshow("Function Test",cleaned_final)
return cleaned_final, [x, y, w, h]
else:
return plate, None
def extract_contours(threshold_img):
# print ('extracting contours')
element = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(17, 3))
morph_img_threshold = threshold_img.copy()
cv2.morphologyEx(src=threshold_img, op=cv2.MORPH_CLOSE, kernel=element, dst=morph_img_threshold)
cv2.imshow("Morphed", morph_img_threshold)
cv2.waitKey(0)
im2, contours, hierarchy = cv2.findContours(morph_img_threshold, mode=cv2.RETR_EXTERNAL,
method=cv2.CHAIN_APPROX_NONE)
return contours
def ratioCheck(area, width, height):
# print ('checking ratio')
ratio = float(width) / float(height)
if ratio < 1:
ratio = 1 / ratio
aspect = 4.7272
min = 15 * aspect * 15 # minimum area
max = 125 * aspect * 125 # maximum area
rmin = 3
rmax = 6
if (area < min or area > max) or (ratio < rmin or ratio > rmax):
return False
return True
def isMaxWhite(plate):
# print ('is Max white')
avg = np.mean(plate)
if (avg >= 115):
return True
else:
return False
def validateRotationAndRatio(rect):
# print( 'validate the rotation and ratio')
(x, y), (width, height), rect_angle = rect
if (width > height):
angle = -rect_angle
else:
angle = 90 + rect_angle
if angle > 15:
return False
if height == 0 or width == 0:
return False
area = height * width
if not ratioCheck(area, width, height):
return False
else:
return True
def cleanAndRead(img, contours):
# print ('clean and read')
# count=0
for i, cnt in enumerate(contours):
min_rect = cv2.minAreaRect(cnt)
if validateRotationAndRatio(min_rect):
x, y, w, h = cv2.boundingRect(cnt)
plate_img = img[y:y + h, x:x + w]
if (isMaxWhite(plate_img)):
# count+=1
clean_plate, rect = cleanPlate(plate_img)
if rect:
x1, y1, w1, h1 = rect
x, y, w, h = x + x1, y + y1, w1, h1
cv2.imshow("Cleaned Plate", clean_plate)
cv2.waitKey(0)
plate_im = Image.fromarray(clean_plate)
plate_im.save('donald1.png')
text = tess.image_to_string(plate_im, lang='eng')
# print text
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Detected Plate", img)
cv2.waitKey(0)
return text
numberplate = 0
img = cv2.imread("car_number_plate.jpg")
threshold_img = preprocess(img)
contours = extract_contours(threshold_img)
# if len(contours)!=0:
# print len(contours) #Test
# cv2.drawContours(img, contours, -1, (0,255,0), 1)
# cv2.imshow("Contours",img)
# cv2.waitKey(0)
plate = cleanAndRead(img, contours)
print ('plate information: ', plate)
If my number plate is: MH01AV8866
It will be recognised as MH01AY8866
Any suggestion will be appreciated. Let me know if any other information is required too.
You are using tesseract as a general model for your problem you can tune your model for that you need to generate synthetic data for your number plates with this
https://github.com/Belval/TextRecognitionDataGenerator
and then you can tune your model using the steps provided
https://github.com/tesseract-ocr/tesseract/wiki/TrainingTesseract-4.00---Finetune
https://github.com/tesseract-ocr/tesseract/wiki/TrainingTesseract-4.00
I've tuned the tesseract on synthetic data and it works like a charm, tried CNN models and tesseract both and tesseract trains better with lesser data and gives better performance.
I am working with a face recognition using OpenCV in python. I want to close this window then open another window when the cam recognized a user. (Nevermind the opening of the window, i already did that) If I just open the another window, it loops and shows plenty of windows. I did search in the internet but no luck. Can someone help me? Here is my code:
import cv2, sys, numpy, os
size = 1
fn_haar = 'data/haarcascade_frontalface_alt.xml'
fn_dir = 'userface'
print('Loading..')
(images, lables, names, img_id) = ([], [], {}, 0)
for (subdirs, dirs, files) in os.walk(fn_dir):
for subdir in dirs:
names[img_id] = subdir
subjectpath = os.path.join(fn_dir, subdir)
for filename in os.listdir(subjectpath):
f_name, f_extension = os.path.splitext(filename)
if (f_extension.lower() not in ['.png','.jpg','.jpeg','.gif','.pgm']):
print("Skipping "+filename+", wrong file type")
continue
path = subjectpath + "/" + filename
lable = img_id
images.append(cv2.imread(path, 0))
lables.append(int(lable))
img_id += 1
(im_width, im_height) = (112, 92)
(images, lables) = [numpy.array(lis) for lis in [images, lables]]
model = cv2.face.FisherFaceRecognizer_create()
model.train(images, lables)
webcam = cv2.VideoCapture(0)
classifier = cv2.CascadeClassifier(fn_haar)
while(True):
rval = False
while(not rval):
(rval, frame) = webcam.read()
if (not rval):
print("Failed to open webcam, Trying again...")
frame = cv2.flip(frame, 1, 0)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
mini = cv2.resize(frame, (int(frame.shape[1] / size), int(frame.shape[0] /
size)))
faces = classifier.detectMultiScale(mini)
for i in range(len(faces)):
face_i = faces[i]
(x, y, w, h) = [v * size for v in face_i]
face = gray[y:y + h, x:x + w]
face_resize = cv2.resize(face, (im_width, im_height))
prediction = model.predict(face_resize)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
if prediction[1]<2300:
cv2.putText(frame, '%s - %.0f' % (names[prediction[0]], prediction[1]),
(x-10, y-10), cv2.FONT_HERSHEY_PLAIN,1,(0, 255, 0))
else:
cv2.putText(frame, 'Unknown', (x-10, y-10), cv2.FONT_HERSHEY_PLAIN,1,(0,
255, 0))
cv2.imshow("Login using Face Recognition", frame)
key = cv2.waitKey(10)
if (key == 27):
break
Im pretty sure you need to create a named window so then you can specifically close that window itself.
You can then destroy the windows when you don't need them anymore:
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Depends on how you use cv2.namedWindow and cv2.imshow.
It could slow down your application if you are using a different winname every time as you would be creating new windows.
I would suggest to just use cv.imshow and modify your code to have a variable that creates a unique title for the current window.
win_name = 'Login using Face Recognition: '
success_count = 0
while(True):
# ... your recognition logic that would set `recognized`
recognized = True
if recognized:
cv2.destroyWindow(win_name + str(success_count))
success_count += 1
cv2.imshow(win_name + str(success_count), frame)
key = cv2.waitKey(10)
if (key == 27):
break
https://snag.gy/6MrLNi.jpg
The chin is a bit off in this photo.
https://snag.gy/ORZHSe.jpg
Not this one.
Difference in Code:
image = cv2.resize(image,(2170, 2894), interpolation = cv2.INTER_AREA)
The second one does not have this line.
Complete Source Code:
import cv2
import sys
import dlib
import numpy as np
from PIL import Image
import rawpy
# Get user supplied values
imagePath = sys.argv[1]
cascPath = "HS.xml"
pointOfInterestX = 200
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("okgood.dat")
raw = rawpy.imread(imagePath)
rgb = raw.postprocess()
image = Image.fromarray(rgb)
#image.save("WOO.jpg")
open_cv_image = np.array(image)
open_cv_image = open_cv_image[:, :, ::-1].copy()
image = open_cv_image
image = cv2.resize(image,(2170, 2894), interpolation = cv2.INTER_AREA)
widthO, heightO = image.shape[:2]
faceCascade = cv2.CascadeClassifier(cascPath)
# Read the image
#image = cv2.imread(imagePath)
gray = cv2.cvtColor((image), cv2.COLOR_RGB2BGR)
#height, width = image.shape[:2]
# Detect faces in the image
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=4,
minSize=(500, 500)
#flags = cv2.CV_HAAR_SCALE_IMAGE
)
newdigit = 0
def test():
for l in range(y, y+h):
for d in range(x, x+w):
# print(image[l,d])
font = cv2.FONT_HERSHEY_SIMPLEX
if all(item < 150 for item in image[l, d]):
cv2.putText(image,"here",(d,l), font, .2,(255,255,255),1,cv2.LINE_AA)
return l;
image[l,d] = [0,0,0]
###
### put hairline 121 pixels from the top.
###
def shape_to_np(shape, dtype="int"):
# initialize the list of (x, y)-coordinates
coords = np.zeros((68, 2), dtype=dtype)
# loop over the 68 facial landmarks and convert them
# to a 2-tuple of (x, y)-coordinates
for i in range(0, 68):
coords[i] = (shape.part(i).x, shape.part(i).y)
# return the list of (x, y)-coordinates
return coords
two = 1
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
print(str(len(faces)))
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
pointOfInterestX = test()
break
dets = detector(image, 1)
one = 0
pointOfEight = 0
for k, d in enumerate(dets):
shape = predictor(image, d)
shape = shape_to_np(shape)
for (x, y) in shape:
if one == 8:
pointOfEight = y
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(image,str(one),(x,y), font, .2,(255,255,255),1,cv2.LINE_AA)
one = one + 1
cv2.circle(image, (x, y), 1, (0, 0, 255), -1)
# loop over the (x, y)-coordinates for the facial landmarks
# and draw them on the image
new_dimensionX = heightO * 631 / (pointOfEight - pointOfInterestX)
new_dimensionY = widthO * 631 / (pointOfEight - pointOfInterestX)
print(str(new_dimensionY))
image = cv2.resize(image,(int(new_dimensionX), int(new_dimensionY)))
Rx = new_dimensionX / heightO
Ry = new_dimensionY / widthO
crop_img = image[int((pointOfInterestX * Rx)-121):int(new_dimensionY), 0:int(new_dimensionX-((Rx *pointOfInterestX)+121))]
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(image,"xxxx",(100,pointOfInterestX ), font, 4,(255,255,255),1,cv2.LINE_AA)
cv2.imshow("Faces found", crop_img)
cv2.imwrite("cropped.jpg", crop_img)
cv2.waitKey(0)
Towards the top you will see the line where I resize the image to 2170,2894. Like I said, with this line absent, the chin detection is accurate. With it, it is not. I need the chin detection accurate at this resolution.
Try to use DLIB's face detector, landmarks detector initialized with face detector ROI, and DLIB's detector ROI is different from OpenCV Haar cascade one. DLIB's landmark detector trained using ROI's from DLIB's face detector, and should work better with it.