JackWeir
JackWeir

Reputation: 75

How to overwrite text using cv2.putText()

I have a dict of as show below which are keys for a virtual keyboard with their keyIndex and text values.

{0: "A", 1: "B", 2: "C", 3: "D"}

I can display these values on a keyboard as below

keyboard = np.zeros((400, 1600, 3), np.uint8)

#key values
width = 100
height = 100
th = 3 # thickness
cv2.rectangle(keyboard, (x + th, y + th), (x + width - th, y + height - th), (246, 248, 250), -1) cv2.line(keyboard, (800, 0), (800, 400), (255, 255, 255), 3)

#Inside the rectangle now we put the letter. So we define the sizes and style of the text and we center it.
#Text settings
font_letter = cv2.FONT_HERSHEY_PLAIN
font_scale = 5
font_th = 4
text_size = cv2.getTextSize(text, font_letter, font_scale, font_th)[0]
width_text, height_text = text_size[0], text_size[1]
text_x = int((width - width_text) / 2) + x
text_y = int((height + height_text) / 2) + y
cv2.putText(keyboard, text, (text_x, text_y), font_letter, font_scale, (0, 0, 0), font_th)

But I want the user to be able to narrow down the set of keys by pressing 'l' or 'r' where left would display only A and B and right would display C and D where the user could then narrow it down again to a single character.

for k in currentSet:
    key(k, currentSet[k])

if currentSet == fullSet and kb.is_pressed('l'):
        currentSet = left
        for k in currentSet:
            key(k, currentSet[k])
elif currentSet == fullSet and kb.is_pressed('r'):
        currentSet = right
        for k in currentSet:
            key(k, currentSet[k])

cv2.imshow("KEYBOARD",keyboard)
cv2.waitKey(0)
cv2.destroyAllWindows()

The above code allows me to display a full set but when I try and press l or r, the program closes.

Any help would be appreciated.

EDIT: Updated loop

currentSet = fullSet
keyboard = np.zeros((400, 1600, 3), np.uint8)


while True:

    keyboard[:] = (255, 255, 255)

    for k in currentSet:
        key(k, currentSet[k])


    cv2.imshow("Keyboard", keyboard)

    kb = cv2.waitKey(0) & 0xff

    if kb == ord('q'):
        break

    if currentSet == fullSet:
        if kb == ord('l'):
            currentSet = left
            print(currentSet)
        if kb == ord('r'):
            currentSet = right
            print(currentSet)

    elif currentSet == left:
        if kb == ord('l'):
            currentSet == left_left
            print(currentSet)
        if kb == ord('r'):
            currentSet == left_right
            print(currentSet)

    elif currentSet == right:
        if kb == ord('l'):
            currentSet == right_left
            print(currentSet)
        if kb == ord('r'):
            currentSet == right_right
            print(currentSet)       


cv2.destroyAllWindows()

This is the keyboard displaying fullSet Full Set

I then press 'l' to select left Left set

Why am I unable to then press 'l' again to set currentSet to left_left?

Upvotes: 0

Views: 1163

Answers (1)

furas
furas

Reputation: 142631

It runs all your is_pressed before you even touch keyboard, and it stops on waitKey(0).

And when you press any key (not only l or r) then it leaves waitKey() and it goes to cv2.destroyAllWindows() and it finishes program.

You have to run it in loop.

  • clean screen
  • draw current set of keys
  • waitKey and get pressed key
  • check key and change set
  • go back to the beginning

Minimal working code

  • q - quit
  • l or left arrow - left part
  • r or right arrow - right part
  • u or up arrow - back to bigger set
  • space or down arrow - copy selected char to text

enter image description here

import cv2
import numpy as np

# --- constans ---  # PEP8: `UPPER_CASE_NAMES` for constants

KEY_WIDTH  = 100
KEY_HEIGHT = 100
TH = 3 # thickness

#Inside the rectangle now we put the letter. So we define the sizes and style of the text and we center it.
#Text settings
FONT_LETTER = cv2.FONT_HERSHEY_PLAIN
FONT_SCALE = 5
FONT_TH = 4

# --- functions ---  # PEP8: `lower_case_names` (verbs) for functions
                     
def draw_key(keyboard, text, x, y):
    cv2.rectangle(keyboard, (x + TH, y + TH), (x + KEY_WIDTH - TH, y + KEY_HEIGHT - TH), (246, 248, 250), -1)

    text_w, text_h = cv2.getTextSize(text, FONT_LETTER, FONT_SCALE, FONT_TH)[0]
    text_x = x + int((KEY_WIDTH  - text_w) / 2)
    text_y = y + int((KEY_HEIGHT + text_h) / 2)

    cv2.putText(keyboard, text, (text_x, text_y), FONT_LETTER, FONT_SCALE, (0, 0, 0), FONT_TH)

# --- main ---  # PEP8: `lower_case_names` (nouns) for variables

full_set  = ['A', 'B', 'C', 'D']
left_set  = ['A', 'B']
right_set = ['C', 'D']

left_left_set  = ['A']
left_right_set = ['B']

right_left_set  = ['C']
right_right_set = ['D']

current_set = full_set

keyboard = np.zeros((400, 1600, 3), np.uint8)

text = []
while True:

    # clean it before drawing new keys    
    keyboard[:] = (0,0,0)

    # draw line    
    cv2.line(keyboard, (800, 0), (800, 400), (255, 255, 255), 3)
        
    # draw keys
    x = 0
    y = 0
    for char in current_set:
        draw_key(keyboard, char, x, y)
        x += KEY_WIDTH + TH
        
    # draw text
    x = 800 + TH
    y = 0
    for char in text:
        draw_key(keyboard, char, x, y)
        x += KEY_WIDTH + TH
    
    # display it 
    cv2.imshow("KEYBOARD", keyboard)
    
    # wait for key
    kb = cv2.waitKey(0) & 0xff
    #print(kb)
    
    # Q - exit
    if kb == ord('q'):
        break
    
    if current_set == full_set:
        if kb == ord('l') or kb == 81: # or left arrow
            current_set = left_set
        if kb == ord('r') or kb == 83: # or right arrow
            current_set = right_set

    elif current_set == left_set:
        if kb == ord('u') or kb == 82: # or up arrow
            current_set = full_set
        if kb == ord('l') or kb == 81: # or left arrow
            current_set = left_left_set
        if kb == ord('r') or kb == 83: # or right arrow
            current_set = left_right_set

    elif current_set == right_set:
        if kb == ord('u') or kb == 82: # or up arrow
            current_set = full_set
        if kb == ord('l') or kb == 81: # or left arrow
            current_set = right_left_set
        if kb == ord('r') or kb == 83: # or right arrow
            current_set = right_right_set

    elif current_set in (left_left_set, left_right_set):
        if kb == ord('u') or kb == 82: # or up arrow
            current_set = left_set
        if kb == ord(' ') or kb == 84: # or down arrow
            print(current_set[0])
            text.append( current_set[0] )

    elif current_set in (right_left_set, right_right_set):
        if kb == ord('u') or kb == 82: # or up arrow
            current_set = right_set
        if kb == ord(' ') or kb == 84: # or down arrow
            print(current_set[0])
            text.append( current_set[0] )

# - end -

cv2.destroyAllWindows()

Upvotes: 1

Related Questions