BigBoy1337
BigBoy1337

Reputation: 5023

How to pass a numpy ndarray as a color in OpenCV?

I am trying to pass a ndarray into this line: cv2.fillPoly(im, pts=[cnt],color=(centroid_color[0],centroid_color[1],centroid_color[2]))

centroid_color looks like this: [ 0 255 0] and is of type <type 'numpy.ndarray'>

However, I keep getting this error: TypeError: Scalar value for argument 'color' is not numeric.

How would I convert this properly?

edit: my current updated code that still gets the same error:

im = cv2.imread('luffy.jpg')
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,0)

contours,h = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    moment = cv2.moments(cnt)
    c_y = moment['m10']/(moment['m00']+0.01)
    c_x = moment['m01']/(moment['m00']+0.01)
    centroid_color = im[c_x,c_y]
    centroid_color = np.array((centroid_color[0],centroid_color[1],centroid_color[2]))
    r = lambda: random.randint(0,255)
    print type(centroid_color)
    cv2.fillPoly(im,cnt,centroid_color)

Upvotes: 4

Views: 8300

Answers (4)

developer0hye
developer0hye

Reputation: 443

color = np.random.randint(low=0, high=256, size=3).tolist()
cv2.rectangle(img, (x, y), (x+w, y+h), color, 3)

Try to use .tolist()

It solved my problem.

You can find usage example on this code.

Upvotes: 0

Tom Hanks
Tom Hanks

Reputation: 362

I followed Automaton2000's answer but no luck in OpenCV 4.4. After tried a thousand times I found that the color param must be passed as list, not np.ndarray. Meanwhile all the other params must be np.ndarray, not list. Well done, OpenCV, for wasting one hour of my time.

import numpy as np
import cv2

pts = np.array([[[10, 40], [70, 16], [100, 90]]], np.int32)
im = np.zeros([240, 320, 3], np.uint8)
# color = np.array((60, 0, 255))  # Not working
color = [60, 0, 255]  # This works
cv2.fillPoly(im, pts, color)

cv2.imshow("Ah, opencv", im)
cv2.waitKey(0)

By the way, here's another example for cv2.rectangle

import numpy as np
import cv2

pts = np.concatenate([np.random.randint(0, 120, (10, 2)), np.random.randint(120, 240, (10, 2))], -1)
im = np.zeros([240, 240, 3], np.uint8)
cv2.rectangle(im, tuple(pts[0, :2]), tuple(pts[0, 2:]), [255, 0, 255])

cv2.imshow("Ah, opencv", im)
cv2.waitKey(0)

Upvotes: 1

mirosval
mirosval

Reputation: 6832

For me the only thing that worked:

self.points = np.int32(np.vstack([
    np.random.uniform(0, bounds[1], 3),
    np.random.uniform(0, bounds[0], 3)
]).T)
color = np.uint8(np.random.uniform(0, 255, 3))

c = tuple(map(int, color))
cv2.fillPoly(img, [self.points], color=c)

Upvotes: 9

Automaton2000
Automaton2000

Reputation: 360

You can pass a numpy array directly as color argument like this:

import numpy as np
import cv2

pts = np.array([[[10,40], [70,16], [100,90] ]], np.int32)
im = np.zeros([240,320, 3], np.uint8)
color = np.array((60,0,255))
cv2.fillPoly( im, pts, color)


cv2.imshow(" ", im)
cv2.waitKey(1)

Of course it is also possible (though unnecessary) to write it like this:

clr = np.array([255, 0, 128])
cv2.fillPoly( im, pts, color=(clr[0], clr[1], clr[2]))

Edit: Opencv requires the color argument to be either an array of float or integer type. The type you get from a 3-channel RGB image is probably uint8. Try adding

centroid_color = centroid_color.astype(np.int32, copy=False)

before you pass the color argument to cv2.fillPoly!

The opencv error message is a little confusing here...

Upvotes: 0

Related Questions