Apr-13-2018, 08:55 PM
I am fairly new to python but have been coding for a long time. I am trying to use OpenCV to detect faces in an image and then iterate through the pixels detected by the face detection. I am then adding all of the RGB values of the image together and then taking an average. It is my hope that this will give me the average skin tone of the person in the photo. But, I am having some trouble with nested loops in python. At first I tried a for loop, but then I realized in python for loops always start at 0 so this was not useful. I then tried a nested while loop as seen below, but was met with an unexpected result. These are on lines 32 to 34.
[inline]
When executed, a blue rectangle will surround a face and a gray line, which represents all of the pixels iterated over, bisects the rectangle diagonally. What I want is for the entire rectangle to be iterated over. I could scan over the correct dimensions with a for loop, but it would start at index 0 0, so this was not useful to my purpose. Please let me know if I need to clarify my question further
[inline]
import numpy as np import cv2 #load xml files, in openCV face_cascade = cv2.CascadeClassifier('C:\Program Files\opencv\sources\data\haarcascades\haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier('C:\Program Files\opencv\sources\data\haarcascades\haarcascade_eye.xml') #define image and convert to grayscale, these are my own images, swap with whatever you want img = cv2.imread('face2.jpg') gray = cv2.imread('face2.jpg',0) #scan for faces and draw rectangle faces = face_cascade.detectMultiScale(gray, 1.3, 5) #these four values are the xy coordinates passed to create the rectangle for face detection x1= faces[0][0] x2= faces[0][2] y1= faces[0][1] y2= faces[0][3] #values to store the RGB values of the face avgR=0 avgB=0 avgG=0 #calculating the other two corners of the rectange as well as the center. topRight= x1 + (x2-x1) bottomLeft= y1 + (y2-y1) centerX= (x2-x1)/2 centerY= (y2-y1)/2 counter=0 off=True #the nested loop that is giving me problems. for() yG= y1 while yG <= bottomLeft: #get the RGB values in each pixel insertRed= img[x1,y1,0] insertGreen= img[x1,y1,1] insertBlue= img[x1,y1,2] #insertRed= img[centerY,centerX,0] #insertGreen= img[centerY,centerX,1] #insertBlue= img[centerY,centerX,2] #add them together avgR= avgR+ insertRed avgG= avgG + insertGreen avgB= avgB +insertBlue #counter is used to get the average counter= counter+1 #this was done for testing to see what the program is actually reading img[x1,yG]= [40,40,40] #increment x1= x1+1 yG=yG+1 #this just draws a rectangle guide around the face for (x,y,w,h) in faces: img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) roi_gray = gray[y:y+h, x:x+w] roi_color = img[y:y+h, x:x+w] #calculate the average of each color avgR= avgR/counter avgG= avgG/counter avgB= avgB/counter cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows() print(avgR, avgG, avgB) input('Press ENTER to exit')[/inline]
When executed, a blue rectangle will surround a face and a gray line, which represents all of the pixels iterated over, bisects the rectangle diagonally. What I want is for the entire rectangle to be iterated over. I could scan over the correct dimensions with a for loop, but it would start at index 0 0, so this was not useful to my purpose. Please let me know if I need to clarify my question further