Detect more than one face OpenCV - python-2.7

i'm learning python so i'm trying to work with OpenCV.
Program detecting only one face, if there will be 2 faces it will be show only one
here's the code:
def getData(id):
psg = psgconnect.cursor()
psg.execute("SELECT name FROM people WHERE id=%s", (Id,))
cursor = psg.execute("SELECT name FROM people WHERE id=%s", (Id,))
Data = None
psgconnect.commit()
row = psg.fetchone()
#psgconnect.close()
return row
while True:
ret, img = cam.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
face = faceDetect.detectMultiScale(gray, 1.3, 5)
for(x, y, w, h) in face:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
Id, conf = recognizer.predict(gray[y:y + h, x:x + w])
data = getData(Id)
# if data != None:
if(conf<50):
#cv2.putText(img, data[0], (x, y + h), cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 4)
cv2.putText(img, 'nashel', (x, y + h), cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 4)
elif(conf>51):
cv2.putText(img, 'Unknown', (x, y + h), cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 4)
cv2.imshow("Face", img)
k = cv2.waitKey(10)
print("suda doshli")
if k == 27:
#psg.close()
psgconnect.close()
print("zdes")
break
cam.release()
input()
cv2.destroyAllWindows()
What wroung could be?

Since you're not getting any answer, I'll try and help you even though I don't use OpenCV.
First, are you sure that OpenCV is only detecting one face in a two-face image or could it be a problem with your loop ?
You could check how many faces are detected by using a simple print:
ret, img = cam.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
face = faceDetect.detectMultiScale(gray, 1.3, 5)
print len(face)
If it prints 1, then there actually is a problem with how OpenCV is working with your image (and in this case I really can't help you because I don't know anything about OpenCV). However, when I read your code, I get the feeling that some things are off (even after your edit), so I propose you tried the following:
def getData(id):
psg = psgconnect.cursor()
psg.execute("SELECT name FROM people WHERE id=%s", (Id,))
cursor = psg.execute("SELECT name FROM people WHERE id=%s", (Id,))
Data = None
psgconnect.commit()
row = psg.fetchone()
#psgconnect.close()
return row
while True:
ret, img = cam.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
face = faceDetect.detectMultiScale(gray, 1.3, 5)
for(x, y, w, h) in face:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
Id, conf = recognizer.predict(gray[y:y + h, x:x + w])
data = getData(Id)
if(conf<50):
cv2.putText(img, 'nashel', (x, y + h), cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 4)
elif(conf>51):
cv2.putText(img, 'Unknown', (x, y + h), cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 4)
cv2.imshow("Face", img)
k = cv2.waitKey(10)
print("suda doshli")
if k == 27:
#psg.close()
psgconnect.close()
print("zdes")
break
cam.release()
input()
cv2.destroyAllWindows()
Let me know how it goes!
As a side note: since you're learning python and considering the code you pasted before your first edit, I would just like to emphasize how important indentation is in python. A change of indentation can completely change the meaning of your code, and it is very important that you understand how and why certain blocks are indented.

Related

How to detect randomly curved non-continuous fixed colored lines from an image?

I am very new in the python openCV. I wanted to find the 7 fixed colored randomly curved lines from an image. The result should be boolean which will give me if the image contains the 7 fixed colored randomly curved lines or not. The sample input image is as below:
I also wanted to find out the non-continuous faint green colored trapezium from the image.
I have written the below code to filter out the specific color from the image but unable to detect the lines & unable to conclude if the image is containing the 7 different lines & trapezium. Below is my sample code for the same:
import cv2
import numpy as np
boundaries = [
(32, 230, 32), # 2 Green lines
(10, 230, 230), # 1 Yellow line
(230, 72, 32), # 1 Blue line
(255, 255, 255), # 2 White lines
(32, 72, 230) # 1 Red line
]
box = [(0, 100, 0), (100, 255, 100)]
image = cv2.imread('testImage5.png')
image = removeBlackBands(image)
# cv2.imshow('Cropped Image', image)
# cv2.waitKey(0)
for row in boundaries:
# create NumPy arrays from the boundaries
row = np.array(row, dtype="uint8")
mask = cv2.inRange(image, row, row)
cv2.GaussianBlur(mask, (5,5), 0)
cv2.imshow('Filtered', mask)
cv2.waitKey(0)
lines = cv2.HoughLinesP(mask, cv2.HOUGH_PROBABILISTIC, np.pi / 180, 50, 50, 100)
if lines is not None:
for x in range(0, len(lines)):
print("line ", x)
for x1, y1, x2, y2 in lines[x]:
print("x1 = {}, y1 = {}, x2 = {}, y2 = {}".format(x1, y1, x2, y2))
cv2.line(image,(x1,y1),(x2,y2),(0,0, 255),2, cv2.LINE_AA)
pts = np.array([[x1, y1], [x2, y2]], np.int32)
cv2.polylines(image, [pts], True, (0, 255, 0))
cv2.imshow('Processed.jpg', image)
cv2.waitKey(0)
# create NumPy arrays from the boundaries
lower = np.array(box[0], dtype="uint8")
upper = np.array(box[1], dtype="uint8")
# find the colors within the specified boundaries and apply
# the mask
mask = cv2.inRange(image, lower, upper)
output = cv2.bitwise_and(image, image, mask=mask)
output = cv2.cvtColor(output, cv2.COLOR_BGR2GRAY)
output = cv2.Canny(output, 100, 150)
# show the images
# cv2.imshow("output", output)
# cv2.waitKey(0)
cv2.destroyAllWindows()
Can somebody help me? Thanks in Advance..!!!
This is the function I wrote for the same.
def detectNodes(self, image, tolerance=0):
"""
Detect the nodes in the image
Algorithm used:
1. Pre-process the image to filter out the required color
2. Convert the pre-processed image to binary image
Args:
image(np.ndarray): Numpy Nd array of image
tolerance: (int): Margin of consideration while extracting color from image. Default: 0
Returns
True upon success, False otherwise
"""
noOfNodesDetected = 0
curveWidth = 2
noOfNodeDetectThreshold = 5
cropH = self.testData["nodalROI"].get("height")
cropW = self.testData["nodalROI"].get("width")
roiImage = ppu.crop(image, cropH, cropW) # Crop node ROI
for color in self.nodalColorBoundaries.keys():
filtered = ImageProc.colorFilter(roiImage, colors=self.nodalColorBoundaries[color], tolerance=tolerance)
bgrImage = ppu.convertColorSpace(filtered, "bgr_to_gray")
thresh = ppu.threshold(bgrImage, 1, "thresh_binary")
logging.info("The shape of image is [{}]".format((thresh.shape)))
height, width = thresh.shape
pointFraction = self.testData.get("pointsToFormEquationOfCurve", None)
points = [int(fraction * height) for fraction in pointFraction]
logging.info("Point using for formulating the equation are [{}]".format(points))
pointFractionEvaluation = self.testData.get("pointsForEvaluationOfCurve", None)
pointsForEvaluation_h = [int(fraction * height) for fraction in pointFractionEvaluation]
logging.info("Point using for Evaluating the equation are [{}]".format(pointsForEvaluation_h))
curve1 = []
curve2 = []
for point in points:
prevX = 0
flag = 0
for w in range(0, width):
if thresh[point][w] == 255:
if (abs(prevX - w)) > curveWidth:
if flag == 0:
curve1.append((point, w))
flag = 1
else:
curve2.append((point, w))
prevX = w
fitter = CurveFitter1D()
if curve2:
logging.error("Second curve detected with color {} having points {}".format(color, curve2))
if curve1:
x1 = [point[0] for point in curve1]
y1 = [point[1] for point in curve1]
logging.qvsdebug("Points using to find the Polynomial with color {} are {} ".format(color, curve1))
fitter._fit_polyfit(x1, y1, 4)
logging.qvsdebug("Coefficient of the Polynomial with color {} are {} ".format(
color, fitter._fitterNamespace.coefs))
else:
logging.error("Points not found with {}".format(color))
return False
pointsForEvaluation_w = [int(round(fitter._predY_polyfit(point))) for point in pointsForEvaluation_h]
logging.qvsdebug(
"Points using for the verification of Polynomial representing curve with color {} are {} ".format(
color, zip(pointsForEvaluation_h, pointsForEvaluation_w)))
counter = 0
for i in range(len(pointsForEvaluation_h)):
if pointsForEvaluation_w[i] + 2 >= width:
continue # Continue if control is reaching to width of iamge - 2
if any(thresh[pointsForEvaluation_h[i]][pointsForEvaluation_w[i] - 2:pointsForEvaluation_w[i] + 3]):
counter += 1
logging.info(
"Out of {} points {} points are detected on the curve for color {}".format(len(pointsForEvaluation_h),
counter, color))
nodeDetectThreshold = int(len(pointsForEvaluation_h) * 0.6)
if counter >= nodeDetectThreshold:
noOfNodesDetected += 1
if noOfNodesDetected >= noOfNodeDetectThreshold:
logging.info("Nodes found in this frame are [%d], minimum expected [%d]" % (
noOfNodesDetected, noOfNodeDetectThreshold))
return True
else:
logging.error("Nodes found in this frame are [%d], minimum expected is [%d]" % (
noOfNodesDetected, noOfNodeDetectThreshold))
return False

Find mean position of blackpixels using python

I have a binary image and I need to find the mean values of x and y of the black region. These values are calculated for a set of binary images and their mean values of x and y are plotted I don't know how to find this region and calculate their mean values of x and y. Any help is kindly appreciated.
If black pixels are not registered in some data structure, just calculate center of mass for black pixels:
sx = 0
sy = 0
black_cnt = 0
for y in y-range
for x in x-range
if black(x,y)
sx = sx + x
sy = sy + y
black_cnt++
sx = sx / black_cnt
sy = sy / black_cnt
You can obtain the mean positions using the moments of contours.
In order to find the mean you must calculate the first order moments of the contour.
CODE:
#---Read image and obtain threshold---
im = cv2.imread('1.jpg', 1)
img = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(img, 120, 255, 1)
#---Obtain contours---
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnts = contours
cv2.drawContours(im, contours, -1, (0, 255, 0), 1)
#---Compute the center/mean of the contours---
for c in cnts:
M = cv2.moments(c)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
print cX
print cY
Values cX and cY have the mean positions of the contours.

Having trouble with cv2.findContours() function

I am unable to find contour and draw a rectangle around it using this video.
Link: http://www.filedropper.com/outcutscaled
Initially, I tried finding contour by simply using the function cv2.findContours() but it was showing some dots. Then i tried applying some morphological transforms but still no luck as contour is not proper.
Can you please tell me what am i doing wrong?
P.S I am using cv2.bitwise_and() to eliminate shadows. One can also use cv2.bitwise_or().
This is my code:
import cv2
def diffImg(t0, t1, t2):
d1 = cv2.absdiff(t2, t1)
d2 = cv2.absdiff(t1, t0)
return cv2.bitwise_and(d1, d2)
cam = cv2.VideoCapture('out_cut_scaled.mp4')
fgbg = cv2.BackgroundSubtractorMOG2(history=50, varThreshold=50)
winName = "Movement Indicator"
cv2.namedWindow(winName, cv2.CV_WINDOW_AUTOSIZE)
# Read three images first:
t_minus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
t = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
t_plus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
while True:
result=diffImg(t_minus, t, t_plus)
#frame = cv2.resize(result, (20, 20))
#fgmask = result
fgmask = cv2.blur(result, (10, 10))
fgmask = fgbg.apply(fgmask)
fgmask = cv2.medianBlur(fgmask, 7)
#ret, thresh = cv2.threshold(result, 127, 255, 0)
thresh = cv2.dilate(fgmask, None, iterations=2)
#thresh = cv2.erode(thresh, None, iterations=2)
"""
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#cv2.drawContours(thresh, contours, -1, (0, 255, 0), 3)
for contour in contours:
x, y, w, h = cv2.boundingRect(contour)
if w > 10 and h > 10:
cv2.rectangle(thresh, (x, y), (x + w, y + h), (0, 255, 0), 2)
print len(contours)
"""
cv2.imshow(winName, thresh)
cv2.imshow("frame", t)
# Read next image
t_minus = t
t = t_plus
t_plus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
key = cv2.waitKey(10)
if key == 27:
cv2.destroyWindow(winName)
break
OpenCV version: 2.4.13
Python version: 2.7
the function cv2.findContours modifies the input image and draws the contours as dots in the image. May be that is why you are getting only dots.
To get the complete contours, use cv2.drawContours with thickness set to some high value and line type as 8.

OCR reading O instead of 0 - C++, Opencv, tesseract

I'm using Tesseract framework with Opencv and C++ to read letters from an image on windows platform. Result contains O instead of 0 in many scenarios. Is there any way to eliminate this and receive an accurate answer?
One possible solution will be to use tessedit_char_whitelist config to specify only the characters that you are searching for.
If you have a well-known text pattern in your image maybe you can crop multiple images and use this config respectively to search for '0' or 'O' when you know they will appear.
Here's one code I made to see this config usage:
import cv2
import numpy as np
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract'
img = cv2.imread('a.jpg')
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(_, blackWhiteImage) = cv2.threshold(grayImage, 127, 255, cv2.THRESH_BINARY)
blackWhiteImage = cv2.copyMakeBorder(src=blackWhiteImage, top=100, bottom=100, left=50, right=50, borderType=cv2.BORDER_CONSTANT, value=(255,255,255))
data = pytesseract.image_to_data(blackWhiteImage, config="-c tessedit_char_whitelist=ABCDEFGHIJKLMNO0123456789 --psm 6")
originalImage = cv2.cvtColor(blackWhiteImage, cv2.COLOR_GRAY2BGR)
for z, a in enumerate(data.splitlines()):
if z != 0:
a = a.split()
if len(a) == 12:
x, y = int(a[6]), int(a[7])
w, h = int(a[8]), int(a[9])
cv2.rectangle(originalImage, (x, y), (x + w, y + h), (0, 255, 0), 1)
cv2.putText(originalImage, a[11], (x, y - 2), cv2.FONT_HERSHEY_DUPLEX, 0.5, (0, 0, 255), 1)
cv2.imshow('final image', originalImage)
cv2.waitKey(0)
You will never achieve a perfect result using OCR. You will always need to do software tricks to try to achieve them.
To improve your results check this from tesseract documentation: Improving the quality of the output

Python DBN dbn.predict use

Hi I am confused with how dbn.predict works I have detected a number in an image using canny and then otsu threshold and resized it to 28x28 etc however when I pass it to dbn.predict I get the following error
ValueError: arrays not aligned for dot product. a dot product was requested of arrays with shapes (1, 28) and (784, 300)
Here is the code for the same, thanks in advance
(cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# sort the contours by their x-axis position, ensuring
# that we read the numbers from left to right
cnts = sorted([(c, cv2.boundingRect(c)[0]) for c in cnts], key = lambda x: x[1])
# loop over the contours
for (c, _) in cnts:
# compute the bounding box for the rectangle
(x, y, w, h) = cv2.boundingRect(c)
# if the width is at least 7 pixels and the height
# is at least 20 pixels, the contour is likely a digit
if w >= 7*scaler and h >= 25*scaler:
# crop the ROI and then threshold the grayscale
# ROI to reveal the digit
roi = gray[y:y + h, x:x + w]
thresh = roi.copy()
T = mahotas.thresholding.otsu(roi)
thresh[thresh > T] = 255
thresh = cv2.bitwise_not(thresh)
#thresh = dataset.deskew(thresh, 28)
#thresh = dataset.center_extent(thresh, (28, 28))
#print thresh.size
#cv2.imshow("Thresh", thresh)
# Resize the image
roi = cv2.resize(thresh, (28, 28), interpolation=cv2.INTER_AREA)
roi = cv2.dilate(roi, (3, 3))
print roi.size
cv2.imshow("ROI", roi)
cv2.waitKey(0)
# Calculate the HOG features
roi_hog_fd = hog(roi, orientations=9, pixels_per_cell=(28, 28), cells_per_block=(1, 1), visualise=False)
nbr = clf.predict(np.array([roi_hog_fd], 'float64'))
pred = dbn.predict(np.atleast_2d(roi/255))