Python Forum
Odd numpy error with subtraction
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Odd numpy error with subtraction
#1
I have this function here which is an answer from a thread of mine a while ago.
def find_closest(color, rgb):
    return rgb[np.argmin(np.abs(rgb - color).sum(axis=1))]
This function finds the closest rgb value (color) in a 2D array of rgb values (rgb).
I have a file named 'test.py', which looks like this:
def find_closest(color, rgb):
    return rgb[np.argmin(np.abs(rgb - color).sum(axis=1))]

color = array([139, 168, 190])
rgb = array([array([144, 157, 178]), array([144, 146, 153]), array([49, 52, 56]), array([92, 84, 69]), array([ 86, 121, 140]), array([170, 141, 107])])                                                                                                                                                                                                          
print(find_closest(color, rgb))
And when run, the output is:
Output:
[144 157 178]
That is exactly what it is supposed to output.

I also have this exact same function, in a different file with a different name. The rgb, although a lot longer, is the exact same. When I say exact, I mean I printed the rgb array from the second file and copied and pasted into the test file.
Instead, when I run it in the second file I get:
Error:
ValueError: operands could not be broadcast together with shapes (1209,) (3,)
This is what's confusing me. There is no difference between the function, the RGB array, the color - there's no difference between anything so how come I am getting an error when I run my second file?
(As I said, I have copied and pasted the rgb array from the second file into 'test.py' so if it was the array wouldn't 'test.py' also error?)
Reply
#2
It seems that rgb array has shape 1209. What is output of print(rgb.shape) in this case?
Reply
#3
(May-30-2020, 12:44 PM)scidam Wrote: It seems that rgb array has shape 1209. What is output of print(rgb.shape) in this case?
Printing both the shape of the rgb array and the single colour array respectively gives:
Output:
(1209,) (3,)
Reply
#4
Ok. find_closest expects that rgb has shape (m, n) and color has shape (n,). In our case n = 3. The only way here is to investigate why rgb has shape (xxxx, ), i.e. why it is one dimensional array (it should be 2D array). Could you please provide minimal reproducible example here that leads to the problem?
Reply
#5
(May-30-2020, 11:25 PM)scidam Wrote: Ok. find_closest expects that rgb has shape (m, n) and color has shape (n,). In our case n = 3. The only way here is to investigate why rgb has shape (xxxx, ), i.e. why it is one dimensional array (it should be 2D array). Could you please provide minimal reproducible example here that leads to the problem?
Here's a very simplified bit of code. You will need a folder with some images (no more than 5 will work):
import numpy as np
import cv2
import glob

rgb, links = [], []

def find_closest(color, rgb):
    return rgb[np.argmin(np.abs(rgb - color).sum(axis=1))]

def get_average(image, path):       
	avg_col_per_row = np.average(image, axis=0)
	avg = np.average(avg_col_per_row, axis=0)

	rgb.append(avg.astype(int).tolist())
	links.append(path)

for l in glob.glob("your_image_path"):
	get_average(cv2.imread(l, cv2.IMREAD_UNCHANGED), str(l))

some_colour = [100,123,14]
print(find_closest(some_colour, np.array(rgb)))
In theory, this should make rgb a 2D array since it's an array, full of arrays with 3 integers inside.
Reply
#6
I've fixed it, and I can't believe what the issue was.
So I was doing some debugging and I thought rather than append the numpy arrays to a python list, how about add them to a numpy array. To do that, I modified my code a bit so it became this:
def get_average(image, path, index):       
	avg_col_per_row = np.average(image, axis=0)
	avg = np.average(avg_col_per_row, axis=0)

	rgb[index][:] = avg.astype(int)

paths = glob.glob("path*")
for l in paths:
	get_average(cv2.imread(l, cv2.IMREAD_UNCHANGED), str(l), paths.index(l))
This was throwing an error - an odd one - or so I thought.
Error:
could not broadcast input array from shape (4) into shape (3)
I started printing the arrays and noticed ones like this: [137.184 143.6512 150.2464 255. ]. That's when it hit me - alpha values!
I changed line 5 to rgb[index][:] = avg.astype(int)[:3], and what do you know, it worked!
After fixing it there I thought "I wonder if that's causing the original issue?". Ireverted my code back to how it was, but with one change:
def get_average(image, path):       
	avg_col_per_row = np.average(image, axis=0)
	avg = np.average(avg_col_per_row, axis=0)

	rgb.append(avg.astype(int)[:3].tolist())

paths = glob.glob("path*")
for l in paths:
	get_average(cv2.imread(l, cv2.IMREAD_UNCHANGED), str(l))
...and it worked!
I was able to put so many pieces together in those few moments, it's insane. It makes total sense why this issue started occuring when I switched from using pillow to cv2 for image processing (by the looks of things, pillow ignores alpha values). It also makes sense that it would sometimes work if I had a small enough set of images.
Although you didn't say it wasn't giving you an error, it now makes sense that it wasn't, because 5 images was probably not enough to have one with an alpha channel.

Anyway, I'm glad it's fixed now.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Numpy error while filling up matrix with Characters august 4 1,847 Apr-13-2022, 10:28 PM
Last Post: august
  forloop to compute sum by alternating from addition to subtraction JulianZ 3 1,807 Apr-02-2022, 09:36 AM
Last Post: DeaD_EyE
Bug Error while importing numpy Erfan 3 3,270 Nov-28-2020, 07:49 AM
Last Post: bowlofred
  Error in importing numpy fullstop 1 1,917 Dec-18-2019, 12:07 PM
Last Post: jefsummers
  Basic subtraction error rix 4 3,411 Oct-11-2019, 06:43 AM
Last Post: buran
  How to make a subtraction within a range of numbers? Alberto 3 10,096 May-08-2017, 09:13 PM
Last Post: ichabod801

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020