1

I have an 1000x1000px image which I want to divide into 10x10 px squares. I have the variable "coordenada" to track the coords of the current 10x10 square (that's why when trying to get the x and y values I multiply by 10).

I want to draw a rectangle surrounding the "current" 10x10 square given by the coords. I get corner 1 (p1) by multiplying the coords by 10 and corner 2 (p2) by doing the same and adding 10. I want the color of the frame to be the same as the color it has in the middle of the square, so I access that color using canvas[x, y], canvas being the name of the image loaded in a numpy array, and typecasting it into a tuple since that is what I read I need to send cv.rectangle. This is the resulting code (minus declaration of canvas and coordenada):

p1 = (coordenada[0] * 10, coordenada[1] * 10)
p2 = (coordenada[0] * 10 + 10, coordenada[1] * 10 + 10)
colorOfFrame = tuple(canvas[(coordenada[0]*10 + 5), (coordenada[1]*10 + 5)])
# testColor = (255, 123, 32)
cv2.rectangle(canvas, p1, p2, colorOfFrame, 2)

When I run this code, I get the following error message:

    cv2.rectangle(canvas, p1, p2, colorOfFrame, 2)
TypeError: function takes exactly 4 arguments (2 given)

I have tried many argument combinations (like sending a rec instead of two points, etc) and the only way I can get it to work is if the tuple I send as the color is defined using constant values, hence the testColor variable. I have seen many examples online where color is sent as a tuple created by functions the same way I did. What is wrong with this way?

Apologies for my english. I'll add the complete code at the end of the question. The idea is to use a Paint-like program where you can draw shapes using a cursor controlled by keyboard on a 100x100 "pixel" area. Color of the pencil is defined as a list and modified by pressing either I, O or P keys, and the cursor is controlled using W A S D. To keep track of where the cursor is, I draw a frame around the pixel and when a movement key is pressed, that frame is deleted (hence the need to draw a rectangle of the inner color), the cursor is modified and then the new frame is drawn. It is very much a work in progress but my work has stop with this error.

import cv2
import numpy as np

canvas = np.zeros((1000, 1000, 3), np.uint8)
canvas = cv2.bitwise_not(canvas)

coordenada = [0, 0]
coordenadasMax = (99, 99)
dibujando = False
cruz = False
color = [255, 255, 255]


def dibujar_pixel():
    if dibujando:
        cv2.rectangle(canvas, (coordenada[0] * 10, coordenada[1] * 10), (coordenada[0] * 10 + 10, coordenada[1] * 10 + 10), color, -1)
    else:
        cv2.rectangle(canvas, (coordenada[0] * 10, coordenada[1] * 10), (coordenada[0] * 10 + 10, coordenada[1] * 10 + 10), color, 2)


def borrar_pixel():
    if not dibujando:
        p1 = (coordenada[0] * 10, coordenada[1] * 10)
        p2 = (coordenada[0] * 10 + 10, coordenada[1] * 10 + 10)
        colorOfFrame = canvas[(coordenada[0]*10 + 5), (coordenada[1]*10 + 5)]
        testColor = (255, 123, 32)
        cv2.rectangle(canvas, p1, p2, colorOfFrame, 2)


cv2.imshow("Canvas", canvas)

while True:
    tecla = cv2.waitKey(1)

    if tecla == 13:  # enter para cambiar entre dibujar o no dibujar
        dibujando = not dibujando

    elif tecla == ord("a"):  # a para ir a la izquierda
        borrar_pixel()
        if coordenada[0] == 0:  # wrapAround si está en el borde izquierdo
            coordenada[0] = coordenadasMax[0]
        else:
            coordenada[0] -= 1
        dibujar_pixel()

    elif tecla == ord("d"):  # d para ir a la derecha
        borrar_pixel()
        if coordenada == coordenadasMax[0]:  # wrapAround si está en el borde derecho
            coordenada[0] = 0
        else:
            coordenada[0] += 1
        dibujar_pixel()

    elif tecla == ord("w"):  # w para ir hacia arriba
        borrar_pixel()
        if coordenada[1] == 0:  # wrapAround si está en el borde superior
            coordenada[1] = coordenadasMax[1]
        else:
            coordenada[1] -= 1
        dibujar_pixel()

    elif tecla == ord("s"):
        borrar_pixel()
        if coordenada[1] == coordenadasMax[1]:
            coordenada[1] = 0
        else:
            coordenada[1] += 1
        dibujar_pixel()

    elif tecla == ord("m"):
        cruz = not cruz

    elif tecla == 21:
        break

    elif tecla == ord("i"):
        if color[0] == 255:
            color[0] = 0
        else:
            color[0] = 255
        dibujar_pixel()

    elif tecla == ord("o"):
        if color[1] == 255:
            color[1] = 0
        else:
            color[1] = 255
        dibujar_pixel()

    elif tecla == ord("p"):
        if color[2] == 255:
            color[2] = 0
        else:
            color[2] = 255
        dibujar_pixel()

cv2.destroyAllWindows()

Thanks!

Jairo
  • 23
  • 3

1 Answers1

3

The error message seems misleading -- it looks like the TypeError stems from colorOfFrame tuple not consisting of int elements (it consists of np.uint8's).

You can avoid the error by explicitly casting pixel values to int. Here is one way to do this:

colorOfFrame = tuple(int(c) for c in canvas[(coordenada[0]*10 + 5), (coordenada[1]*10 + 5)])
cv2.rectangle(canvas, p1, p2, colorOfFrame, 2)
vasiliykarasev
  • 851
  • 4
  • 10