1

I'm trying to enumerate a 2D NumPy array of shape (512, 512) with pixel values, to output [y_index, x_index, pixel_value]. Output array should have shape (262144, 3): 262144 pixels from 512x512 matrix and 3 for columns pixel value, y coordinate and x coordinate.

I used ndenumerate but how to store values in an array? My attempt at last line is incorrect:

img = as_np_array[:, :, 0]
img = img.reshape(512, 512)
coordinates = np.empty([262,144, 3])
for index, x in np.ndenumerate(img):
    coordinates = np.append(coordinates, [[x], index[0], index[1]])

Intel Core i7 2.7GHz (4 cores) takes 7-10 minutes. Is there a more efficient way?

7
  • Can't you use three variables for pixel value, x coordinate and y coordinate. In that case, you can use the existing array, and ycoord, xcoord = numpy.mgrid[0:img.shape[0],0:img.shape[1]]. Commented Sep 5, 2019 at 5:29
  • Thank you for your response. Sorry, but I didn't understand your particular format of answer. Basically I need an array output with 3 columns: pixel value, and its x & y coordinates. Reason I need that format specifically is because I need to then save it as a CSV file to have that specific data format/structure. You have ycoord, xcoord but I need everything in one array output. Commented Sep 5, 2019 at 12:57
  • Not necessarily: you could also create a double loop over the x- and y-coordinates, and then output a line of x, y, pixel_value to the CSV file. In which case, you neither need that large a 2D array, nor my solution, but just something like for x in range(512): for y in range(512): csv.write(x, y, img[y,x]). Commented Sep 5, 2019 at 13:01
  • Many thanks for this suggestion. I'm just trying out this code right now. I tried this code as a test run with a small array example: array2 = np.array([[1,1,1], [2,2,2], [3,3,3]]) with open('csv_test.csv', 'w', newline='') as f: thewriter = csv.writer(f) thewriter.writerow(['x_coord', 'y_coord', 'pixel_value']) for y in np.nditer(array2): for x in np.nditer(y): thewriter.writerow([x, y, array2[y,x]]), but I got the error: index 3 is out of bounds for axis 0 with size 3. Not sure why is that? Is np.nditer the issue or is it something else? Commented Sep 5, 2019 at 13:59
  • 1
    Because np.nditer steps through the flattened array, which is larger than one dimension. Also, your code doesn't not reflect what I wrote. I step through the dimensions (shape) of the array; you step through the array itself, and use the values inside the to index the array: for y in np.nditer(array2): ... array2[y,x]. That's not going to work (except in some very special cases). Commented Sep 5, 2019 at 14:07

2 Answers 2

1

You could use numpy.indices to do this. What you want ultimately is image_data with y, x indices and the corresponding pixels (px). There are three columns in image_data.

row, col = np.indices(img.shape)
y, x, px = row.flatten(), col.flatten(), img.flatten()
image_data = np.array([y, x, px]).T

Detailed Example:

img = np.arange(20).reshape(5, 4)

def process_image_data(img):
    row, col = np.indices(img.shape)
    return (row.flatten(), col.flatten(), img.flatten())

y, x, px = process_image_data(img)
Sign up to request clarification or add additional context in comments.

Comments

0

The solution that worked for me is this:

with open('img_pixel_coor1.csv', 'w', newline='') as f:
    headernames = ['y_coord', 'x_coord', 'pixel_value']
    thewriter = csv.DictWriter(f, fieldnames=headernames)
    thewriter.writeheader()     
    for index, pix in np.ndenumerate(img):
        thewriter.writerow({'y_coord' : index[0], 'x_coord' : index[1], 'pixel_value' : pix})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.