I'm trying to make a face detection program using OpenCV from an open source tutorial. The goal is to detect face from a video which result is used to be a model for each face.
Each face will be saved in folder, i have 2 problems when i try the program:
OpenCV is not only capturing the face but the whole video
Only 1 picture taken, while more than 1 needed (every frame)
#insert picture 1
Are there any solutions?
Here's the code :
model = cv2.CascadeClassifier("../model/haarcascade_frontalface_alt2.xml")
cap = cv2.VideoCapture('../video/videoplayback.mp4') #Video
while True:
ret, image = cap.read()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
bounding_box = model.detectMultiScale(gray, scaleFactor=1.01,
minNeighbors=5, minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE)
for (x, y, w, h) in bounding_box:
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
image2 = image[y:(y+h),x:(x+w)]
image3 = cv2.blur(image2, (40,40))
image[y:(y+h),x:(x+w)] = image3
cv2.imwrite("../output_model/videos/image.jpg", image)
cv2.imshow("hasil", image)
if cv2.waitKey(1) and 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()```
To take only faces, it is necessary to take variables that are taken from the face only (It is in the image2 variable). What you do when it detects the video will blur the detected face so that it can pick up the blurred part.
image2 = image[y:(y+h),x:(x+w)]
cv2.imwrite("../output_model/videos/{}.jpg".format(counter), image2)
Can be tricked by increments and loops that are performed when loading face images. And each folder is filled with increments. Here's an example:
counter = 0 #Increment
while True:
ret, image = cap.read()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
bounding_box = detector_wajah.detectMultiScale(gray, scaleFactor=1.01,
minNeighbors=5, minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE)
for (x, y, w, h) in bounding_box:
counter+=1 #Increment
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
image2 = image[y:(y+h),x:(x+w)]
For completeness (and there are variables that are changed) as follows:
import cv2
model = cv2.CascadeClassifier("../model/haarcascade_frontalface_alt2.xml")
cap = cv2.VideoCapture('../video/videoplayback.mp4') #Video
counter = 0
while True:
ret, image = cap.read()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
bounding_box = model.detectMultiScale(gray, scaleFactor=1.01,
minNeighbors=5, minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE)
for (x, y, w, h) in bounding_box:
counter+=1
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
face = image[y:(y+h),x:(x+w)]
cv2.imwrite("../output_model/videos/{}.jpg".format(counter), face)
blur_face = cv2.blur(face, (40,40))
image[y:(y+h),x:(x+w)] = blur_face
cv2.imshow("hasil", image)
if cv2.waitKey(1) and 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Related
I am using pyzbar. Of the 13 images, he recognized and decoded 5. Can I improve the result by converting the images through opencv?
I know that there is a QrCodeDetector in opencv, but it does worse with recognition.
my code:
for i in imgs:
image = i
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gradX = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
gradY = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=-1)
gradient = cv2.subtract(gradX, gradY)
gradient = cv2.convertScaleAbs(gradient)
blurred = cv2.blur(gradient, (9, 9))
(_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
closed = cv2.erode(closed, None, iterations=1)
closed = cv2.dilate(closed, None, iterations=1)
(cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
rect = cv2.minAreaRect(c)
box = np.int0(cv2.boxPoints(rect))
x, y, w, h = cv2.boundingRect(box)
if w <= 0 or h <= 0 or y <=0 or x<= 0:
continue
out = image[y:y+h, x:x+w]
pyzbar.decode(out)
cv2.drawContours(image, [box], -1, (0, 255, 0), 3)
cv2.resize(image, (1410, 810))
cv2.imshow("finalImg", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
I thought that if I cut the qr codes from the image myself, then it would be easier for pyzbar to recognize and decipher them. But he began to recognize even fewer qr codes.
In this image I am trying to detect horizontal lines. The code works well when image is not skewed. However, it is not working on such skewed images. I have tried this method to detect the right angle by histogram but many times is actually making it more skewed - python-opencv-skew-correction-for-ocr
Below is code to detect horizontal lines:
gray=cv2.cvtColor(img_final_bin,cv2.COLOR_BGR2GRAY)
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (100,1))
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts, hierarchy = cv2.findContours(detected_lines, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
boundingBoxes = [list(cv2.boundingRect(c)) for c in cnts]
Below is the code for skew correction, which is giving wrong results to me:
def correct_skew(image, delta=0.001, limit=3):
def determine_score(arr, angle):
data = inter.rotate(arr, angle, reshape=False, order=0)
histogram = np.sum(data, axis=1)
score = np.sum((histogram[1:] - histogram[:-1]) ** 2)
return histogram, score
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
print("thresh", thresh.shape)
thresh1 = thresh[0:500, 0:500]
print("thresh1", thresh1.shape)
scores = []
angles = np.arange(-limit, limit + delta, delta)
for i, angle in enumerate(angles):
histogram, score = determine_score(thresh1, angle)
scores.append(score)
# if i%100 == 0:
# print(score, angle, len(angles), i)
best_angle = angles[scores.index(max(scores))]
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, best_angle, 1.0)
rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, \
borderMode=cv2.BORDER_REPLICATE)
return best_angle, rotated
Python Wand, which is based upon ImageMagick has a deskew function.
Input:
from wand.image import Image
from wand.display import display
with Image(filename='table.png') as img:
img.deskew(0.4*img.quantum_range)
img.save(filename='table_deskew.png')
display(img)
Result:
I would like to use the below code in kalman filter of facial landmarks detection to stabilize the landmark.
Any ideas?
import cv2
import numpy as np
import dlib
cap = cv2.VideoCapture(0)
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks")
while True:
_, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = detector(gray)
for face in faces:
x1 = face.left()
y1 = face.top()
x2 = face.right()
y2 = face.bottom()
#cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 3)
landmarks = predictor(gray, face)
for n in range(0, 68):
x = landmarks.part(n).x
y = landmarks.part(n).y
cv2.circle(frame, (x, y), 4, (255, 0, 0), -1)
cv2.imshow("Frame", frame)
key = cv2.waitKey(1)
if key == 27:
break
I'm trying to work on an image-processing. So, I need to grab the max and min area of the contour under for pic, contour in enumerate(contours): after selecting the min area if (area > 2000):
I could grab the max and min of the contour outside for loop, the problem that I need which min contour greater than 2000 in this code.
my full code:
import cv2
import numpy as np
from imutils.video import FPS
import time
cap = cv2.VideoCapture(0)
width = cap.get(3) # float
height = cap.get(4) # float
print width, height
time.sleep(2.0)
fps = FPS().start()
while (1):
_, img = cap.read()
if _ is True:
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
else:
continue
blue_lower = np.array([86,0,90], np.uint8)
blue_upper = np.array([163, 64, 145], np.uint8)
blue = cv2.inRange(hsv, blue_lower, blue_upper)
kernal = np.ones((9, 9), "uint8")
blue = cv2.dilate(blue, kernal)
res_blue = cv2.bitwise_and(img, img, mask=blue)
(_, contours, hierarchy) = cv2.findContours(blue, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for pic, contour in enumerate(contours):
area = cv2.contourArea(contour)
if (area > 2000):
print area
x, y, w, h = cv2.boundingRect(contour)
img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
cv2.putText(img, "Blue Colour", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0))
if len(contours) > 0:
c = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(c)
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 0), 5)
cv2.putText(img, "Blue Colour", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0))
cv2.imshow("Color Tracking", img)
if cv2.waitKey(10) & 0xFF == ord('q'):
cap.release()
cv2.destroyAllWindows()
break
fps.update()
Any ideas or suggestions will be appreciated
I want to extract some rectangles at the top from a UML sequence diagram in jpg format by using OpenCV.
The algorithm I use finds way too many rectangles that are super small and not needed.
I think the mess up is somewhere in the beginning of the code where I apply canny edge detection but I am not sure.
I want to capture only the big rectangles from the top and center.
Thanks for any help.
import cv2
import numpy as np
import imutils
image = cv2.imread("./diagrams/sd2.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 90, 150, 3)
cnts = cv2.findContours(edges, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
cv2.drawContours(image, cnts, -1, (0, 255, 0), 1)
def detect(c):
shape = "unidentified"
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.03 * peri, True)
if len(approx) == 4:
(x, y, w, h) = cv2.boundingRect(approx)
ar = w / float(h)
shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"
return shape
# loop over the contours
for c in cnts:
M = cv2.moments(c)
if M["m00"] != 0:
cX = int((M["m10"] / M["m00"]))
cY = int((M["m01"] / M["m00"]))
shape = detect(c)
c = c.astype("float")
c = c.astype("int")
if(shape == "rectangle"):
cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
cv2.putText(image, shape, (cX, cY), cv2.FONT_HERSHEY_SIMPLEX,
0.5, (0, 0, 0), 2)
# show the output image
cv2.imshow("Image", image)
cv2.waitKey(0)