openCV Cascade Classifier rectangle box and its 4 coordinates - opencv

I am trying to figure rectangle coordinates (4 points) that comes up when a object or face is detected using Cascade Classifier
I am using python and the code is based on the widely available sample:
import cv2
custom_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
def find_face(img):
to_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
object_detected = custom_cascade.detectMultiScale(to_gray, 1.4, 4)
for (x, y, w, h) in object_detected:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 1)
# NOTE
# Circle coordinate shows start of the corner (very top left)
# Need to find all four coordinate of the rectangle
cv2.circle(img, (x, y), 2, (0, 255, 0), 2)
return x, y, w, h
How i can get the pixel coordinates and manipulate it? Is it the same with x + w & y + h or some way around. What if i need to find centroid of an object?

(x, y) are the top left coordinates of the rectangle drawn by cv2.rectangle. w is the width and h is the height
You can manipulate that value to get the midpoint
or another way you can use cv2.boundingRect (cnt)

if you want to find centroid change this line cv2.circle(img, (x, y), 2, (0, 255, 0), 2) to this
cent_x = int( x+w/2) cent_y = int(y+h/2) cv2.circle(img, (cent_x,cent_y), 2, (0, 255, 0), 2)

Ok guys,
After brushing up my openCV and maths a bit and went through some docs, this one works:
center_point_x = abs(x + 0.5 * w)
center_point_y = abs(y + 0.5 * h)
cv2.circle(img, (int(center_point_x), int(center_point_y)), 2, (255, 0, 255), 2)
There is possibilities to use numpy as well. But i did a quick one to check for the operation. Hopefully this will help others.
Thank you all.

Related

Iterating over an image given a numpy ndarray for certain colored pixels in it

I have an image which is all black and white and has a certain colored pixels over the black part, which is pink(those colored pixels are all same i.e., they have have same rgb values).
I have the numpy ndarray for those pink pixels in the image. And using that ndarray i want to traverse the image , in such a way that for every colored pink pixel i go orthogonal(with yellow i have depicted the direction where i need to travel).
I somehow need to find out the width of the black part doing so.
90 degrees to that pixel depiction:
[![90 degrees to that pixel depiction][1]][1]
I basically need to note down the sharp change in the pixels while i do so, the moment i see a transition between black pixels to white i need to note down that distance from the point of the colored pixel to the point of transition.
i had written this code which showed me the pixels in an image(rgb) but is not working for my current example here..
for i, j in np.ndindex(img.shape[:-1]):
print(img[i,j])
Here is how, with the input image (image.png) as:
import cv2
import numpy as np
img = cv2.imread("image.png")
h, w, _ = img.shape
x, y = 300, 160 # Random point on the pink line
strip = img[:, x]
diff = np.diff(np.sum(strip, 1))
# Get y coordinates where...
# white -> black
# black -> pink
# pink -> black
# black -> white
y1, y2, y3, y4 = np.where(diff)[0]
cv2.line(img, (x, y1), (x, y2), (0, 0, 255), 5)
cv2.line(img, (x, y3), (x, y4), (0, 0, 255), 5)
cv2.putText(img, str(y1), (x, y2 - 20), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
cv2.putText(img, str(h - y3), (x, y4 - 20), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
cv2.imshow("result", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Output:

How to put bounding box only after the entire object is completely within region of interest?

This is the image i get..
I have set the left side of red line vertically as the region of interest. Trained a model to detect licence plate where boxes contains the detected object coordinates within ROI. The bounding box appears even before the entire object is within the region of interest. I want the bounding box to appear only after the entire object is within the ROI. This is my code for the bounding box.
x, y, w, h = boxes1[i]
label = ""
color = (0, 0, 255)
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
Draw the rectangle only if x + w is at the left side of the red line.
red_line_x = 200 # for example
x, y, w, h = boxes1[i]
if (x + w) < red_line_x:
color = (0, 0, 255)
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)

Opencv, combination of chroma key correction and contour detection gives unexpected result

I am doing contour detection on a chroma key corrected image. Everything works fine when I filter out just the blues, but when I try to get a better chroma correction by also filtering the reds, suddenly my contours cannot be detected anymore. Anyone any suggestions?
WITH BLUE FILTER:
img = cv2.imread('yellowcropped.jpg', 1)
lower_blue = np.array([0, 0, 15]) ##[R value, G value, B value]
upper_blue = np.array([255, 255, 60])
mask = cv2.inRange(image_copy, lower_blue, upper_blue)
WITH BLUE AND RED FILTER:
lower_blue = np.array([180, 0, 15]) ##[R value, G value, B value]
upper_blue = np.array([255, 255, 60])
(notice the top left image get's much crisper, but NO CONTOURS are detected anymore.)
BELOW MY CONTOUR FINDING CODE:
imgContour = image_original.copy()
imgBlur = cv2.GaussianBlur(img, (7, 7), 1)
imgGray = imgBlur
imgCanny = cv2.Canny(imgGray,threshold1,threshold2)
kernel = np.ones((5, 5))
imgDil = cv2.dilate(imgCanny, kernel, iterations=1)
getContours(imgDil,imgContour)
def getContours(img,imgContour):
""" DRAWS AND FINDS CONTOURS, THEN RETURNS a list of lists incl x0, y0, w, h"""
contour_list = []
contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# print('contours:', contours)
for cnt in contours:
area = cv2.contourArea(cnt)
areaMin = cv2.getTrackbarPos("Area", "Parameters")
if area > areaMin and area < 5000:
cv2.drawContours(imgContour, cnt, -1, (255, 0, 0), 7)
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
# print(len(approx))
x , y , w, h = cv2.boundingRect(approx)
print('contour bounding:', x,y,w,h)
center_x = int(x + w/2)
center_y = int(y + h/2)
cv2.circle(imgContour,(center_x, center_y), 5, (0, 0, 255), 5)
cv2.rectangle(imgContour, (x , y ), (x + w , y + h ), (0, 255, 0), 5)
cv2.putText(imgContour, "Points: " + str(len(approx)), (x + w + 20, y + 20), cv2.FONT_HERSHEY_COMPLEX, .7,
(0, 255, 0), 2)
cv2.putText(imgContour, "Area: " + str(int(area)), (x + w + 20, y + 45), cv2.FONT_HERSHEY_COMPLEX, 0.7,
(0, 255, 0), 2)
if area < 3500:
cv2.putText(imgContour, "THIS IS A SMALL PART" , (x + w + 20, y + 70), cv2.FONT_HERSHEY_COMPLEX, 0.7,
(0, 255, 0), 2)
contour_list.append([x,y,w,h])
return contour_listenter code here
So i still do not entirely know what went wrong here but I found a solution for anyone in the future looking to first chroma key correct (Remove background) and then do contour detection:
I dropped the gaussian filter, dilate and canny and instead just inverted the image's colours (contour detection only detects white parts on black background) using:
mask = cv2.bitwise_not(mask)
I then changed the contour detection from cv2.RETR_EXTERNAL to cv2.RETR_LIST
Somehow that fixed it, the result is now really good.

How to calculate dimension of image by knowing pixels and distance between camera and object?

I have written a code in opencv-python for calculating the number of pixels in height and width of an object.
Lets say,
height = 567 pixels
width = 324 pixels
I also have KNOWN_FOCAL_LENGTH of camera and distance between the original object and camera.
# Getting the biggest contour
cnt = max(contours, key = cv2.contourArea)
cv2.drawContours(image, cnt, -1, (0, 255, 0), 3)
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.005* peri, True)
# get the bounding rect
x, y, w, h = cv2.boundingRect(approx)
print("Width in pixels : {}, Height in pixels : {}".format(w,h))
# draw a green rectangle to visualize the bounding rect
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
WidthData = "Width : {} mm".format(round(w/scaling_factor,2))
HeightData = "Height : {} mm".format(round(h/scaling_factor,2))
textData = WidthData + ", " + HeightData
cv2.putText(image, textData, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2)
print(WidthData)
print(HeightData)
cv2.imshow('Result', image)
How can I calculate the factor with which I can convert my number_of_pixels to original_length of
image ?
How to calculate scaling_factor ?
You need a way to convert a measurement in pixels to one in meters. Possible ways to do that are, in order of accuracy.
Look up the physical dimensions of the camera sensors, e.g. from the spec sheet of the camera or, if you are lucky, from the metadata stored in the image along with the pixels (EXIF header)
Place an object of known size in the scene.
Directly scale the focal length from pixels to mm as given by the lens.

Trying to detect faces using OpenCv's inbuilt face detector

Face Detection using OpenCV's inbuilt face detector.
What does the code between the asterisks mean?
A caffe model is being used here.
# loop over the detections
for i in range(0, **detections.shape[2]**):
# extract the confidence (i.e., probability) associated with the
# prediction
confidence = **detections[0, 0, i, 2]**
# filter out weak detections by ensuring the `confidence` is
# greater than the minimum confidence
if confidence > args["confidence"]:
# compute the (x, y)-coordinates of the bounding box for the
# object
**box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")**
# draw the bounding box of the face along with the associated
# probability
text = "{:.2f}%".format(confidence * 100)
**y = startY - 10 if startY - 10 > 10 else startY + 10
cv2.rectangle(image, (startX, startY), (endX, endY),
(0, 0, 255), 2)**
cv2.putText(image, text, (startX, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
# show the output image
cv2.imshow("Output", image)
cv2.waitKey(0)

Resources