-1

I have this simple Python code that makes predictions on the emotions of the face (refer to here in case you need to run it), whether the person is happy, sad, etc. It uses cv2 and Keras. Now, I would like to visualize and place a meter on the frame based on the probability of each frame (prob value below which is a percentage). How can I do that?

Something like this. Don't worry about the colors for now.

enter image description here

cap = cv2.VideoCapture(1)

canvasImage = cv2.imread("fg2.png")

x0, x1 = 330, 1290
y0, y1 = 155, 700


prediction_history = []
LOOKBACK = 5 # how far you want to look back

counter = 0
while True:
    # Find haar cascade to draw bounding box around face
    ret, frame = cap.read()
    frame=cv2.flip(frame,3)
    if not ret:
        break
    facecasc = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    faces = facecasc.detectMultiScale(gray,scaleFactor=1.3, minNeighbors=5)

    for (x, y, w, h) in faces:
        cv2.rectangle(frame, (x, y-50), (x+w, y+h+10), (255, 0, 0), 2)
        roi_gray = gray[y:y + h, x:x + w]
        cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray, (48, 48)), -1), 0)
        prediction = model.predict(cropped_img)
        
        maxindex = int(np.argmax(prediction))
        text = emotion_dict[maxindex]
        prob = round(prediction[0][3]*100, 2)
        
        prediction_history.append(maxindex)
        most_common_index = max(set(prediction_history[-LOOKBACK:][::-1]), key = prediction_history.count)
        text = emotion_dict[most_common_index]
        
        #if ("Sad" in text) or ("Angry" in text) or ("Disgusted" in text):
        #    text = "Sad"
        if ("Happy" in text) or ("Sad" in text) :
            cv2.putText(frame, text+": "+str(prob), (x+20, y-60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
  

    dim = (800,480)
    frame_shrunk = cv2.resize(frame, (x1 - x0, y1 - y0))
    canvasImage[y0:y1, x0:x1] = frame_shrunk
    #cv2.imshow('Video', cv2.resize(frame,dim,interpolation = cv2.INTER_CUBIC))
    cv2.imshow('Demo', canvasImage)
    
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
Tina J
  • 4,983
  • 13
  • 59
  • 125

1 Answers1

1

There is no built in function in OpenCV for drawing meters, here is a helper function that you can use to draw a meter over an image:

def draw_indicator(img, percentage):

    def percentage_to_color(p):
        return 0, 255 * p, 255 - (255 * p)

    # config
    levels = 10
    indicator_width = 80
    indicator_height = 220
    level_width = indicator_width - 20
    level_height = int((indicator_height - 20) / levels - 5)
    # draw
    img_levels = int(percentage * levels)
    cv2.rectangle(img, (10, img.shape[0] - (indicator_height + 10)), (10 + indicator_width, img.shape[0] - 10), (0, 0, 0), cv2.FILLED)

    for i in range(img_levels):
        level_y_b = int(img.shape[0] - (20 + i * (level_height + 5)))
        cv2.rectangle(img, (20, level_y_b - level_height), (20 + level_width, level_y_b), percentage_to_color(i / levels), cv2.FILLED)

# test code
img = cv2.imread('a.jpg')
draw_indicator(img, 0.7)
cv2.imshow("test", img)
cv2.waitKey(10000)
Black0ut
  • 1,642
  • 14
  • 28
  • Thanks! Instead of red to green, how can I have a shade of green (light green to dark green)? – Tina J Oct 13 '21 at 18:38
  • 1
    You can try replace return return 0, 255 * p, 255 - (255 * p), 0 with return 0, 255 - (200 * p), 0 – Black0ut Oct 13 '21 at 18:46
  • Nice. Sorry one last question: How about slightly yellow-ish to more green? – Tina J Oct 13 '21 at 18:59
  • And can you add argument for (x,y) for coords of where we can place it on the window? I would like it to be more in the middle than botton. – Tina J Oct 13 '21 at 19:02
  • I posted these requests under a new question:) https://stackoverflow.com/questions/69562289/how-to-change-colors-on-my-pythons-cv2-diagram – Tina J Oct 13 '21 at 21:03