How to get all pixs by certain indices from a image array - python

The image array shape is (540, 960, 3), and it like this:
img_rgb = [[[ 95 71 71]
[ 95 71 71]
[ 95 71 71]
...
[182 171 181]
[182 171 181]
[182 171 181]]
[[ 95 71 70]
[ 95 71 70]
[ 95 71 71]
...
[183 172 182]
[183 172 182]
[183 172 182]]
[[ 95 72 70]
[ 95 71 70]
[ 95 71 71]
...
[183 172 182]
[183 172 182]
[183 172 182]]
...
[[ 36 35 45]
[ 36 35 45]
[ 36 35 45]
...
[ 49 45 50]
[ 49 45 50]
[ 49 45 50]]
[[ 36 35 45]
[ 36 35 45]
[ 36 35 45]
...
[ 49 45 50]
[ 49 45 50]
[ 49 45 50]]
[[ 36 35 45]
[ 36 35 45]
[ 36 35 45]
...
[ 49 45 50]
[ 49 45 50]
[ 49 45 50]]]
And I want to get elements by indices that indicate the each element index, and the indices like this:
indices = [
[0, 0], [0, 1], [0, 2]
]
Expected output
[
[ 95 71 71],
[ 95 71 71],
[ 95 71 71],
]
There are tow similar question in those link, one is Python numpy 2D array sum over certain indices, and another is Finding the (x,y) indexes of specific (R,G,B) color values from images stored in NumPy ndarrays.
It got a IndexError: too many indices for array When I tried question one by img_rgb[tuple(indices)].

You just need to transpose indices.
img_rgb[tuple(np.transpose(indices))]
np.tranpose() would work even if indices is just a list, since it expects as input any "array-like" structure.

Related

How can I get uneven submatrices from NxN matrix?

I have a large NxN matrix that I'm looking to retrieve multiple submatrices from. Each of these submatrices can be different sizes but they can't overlap (see attached pic). Is there a function in Python that could remotely do what I'm looking to achieve?
example of submatrices in NxN matrix
This is what I've written so far; however, it doesn't give me back a square submatrix
import numpy as np
# Create a 10x10 matrix
matrix = np.arange(0, 100).reshape((10, 10))
print(matrix)
# Define the sizes of the submatrices
submatrix_sizes = [4, 4, 5]
# Calculate the starting and ending indices for each submatrix
starts = np.cumsum([0] + submatrix_sizes[:-1])
ends = np.cumsum(submatrix_sizes)
# Split the matrix into submatrices of the specified sizes
submatrices = np.split(matrix, ends, axis=1)[:-1]
# Print the submatrices
for i, submatrix in enumerate(submatrices):
print(f"Submatrix {i+1}:")
print(submatrix)
Output
[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28 29]
[30 31 32 33 34 35 36 37 38 39]
[40 41 42 43 44 45 46 47 48 49]
[50 51 52 53 54 55 56 57 58 59]
[60 61 62 63 64 65 66 67 68 69]
[70 71 72 73 74 75 76 77 78 79]
[80 81 82 83 84 85 86 87 88 89]
[90 91 92 93 94 95 96 97 98 99]]
Submatrix 1:
[[ 0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]
[50 51 52 53]
[60 61 62 63]
[70 71 72 73]
[80 81 82 83]
[90 91 92 93]]
Submatrix 2:
[[ 4 5 6 7]
[14 15 16 17]
[24 25 26 27]
[34 35 36 37]
[44 45 46 47]
[54 55 56 57]
[64 65 66 67]
[74 75 76 77]
[84 85 86 87]
[94 95 96 97]]
Submatrix 3:
[[ 8 9]
[18 19]
[28 29]
[38 39]
[48 49]
[58 59]
[68 69]
[78 79]
[88 89]
[98 99]]
Your starts and ends are not calculated correctly:
It is impossible to have index of 13 on any axis on a 10x10 matix.
you don't use the calculated starts while slicing
starts = np.cumsum([0] + submatrix_sizes[:-1])
# has to be disiced how to calculate these correctly
ends = np.cumsum(submatrix_sizes)
breaks = list(zip(starts, ends))
# slicing x and y axis not only x
submatrix_sizes = [matrix[elem[0]:elem[1], elem[0]:elem[1]] for elem in breaks]

Convert array in string format from cell in pd.DataFrame to ndarray in python

I got an dataframe where one column is image pixels as arrays in string format and I want to convert them to actual arrays.
Here an example where I printed one cell.
X[0] = `
[[[164 164 164]
[164 164 164]
[162 162 162]
...
[ 54 54 54]
[ 54 54 54]
[ 54 54 54]]
[[164 164 164]
[164 164 164]
[162 162 162]
...
[ 54 54 54]
[ 54 54 54]
[ 54 54 54]]
[[164 164 164]
[164 164 164]
[162 162 162]
...
[ 54 54 54]
[ 54 54 54]
[ 54 54 54]]
...
[[ 84 84 84]
[ 84 84 84]
[ 84 84 84]
...
[ 50 50 50]
[ 51 51 51]
[ 51 51 51]]
[[ 84 84 84]
[ 84 84 84]
[ 83 83 83]
...
[ 51 51 51]
[ 51 51 51]
[ 51 51 51]]
[[ 84 84 84]
[ 84 84 84]
[ 84 84 84]
...
[ 51 51 51]
[ 51 51 51]
[ 51 51 51]]]
I tried doing it in a preprocessing step but that doesn't work
def preprocess(image):
"""
Takes an image array, turns it into tensor and normalizes the values
"""
image = tf.cast(np.ndarry(image), tf.float32)
# turn arrays of data into tensors
image = tf.convert_to_tensor(image, tf.float32)
# normalize image
image = image/255.0
return image
preprocess(X[0])
EDIT (format the dataset to be a dataframe structure with arrays and labels):
def create_data(datadir):
"""
Creates a list of images and their labels from a given directory (datadir)
"""
for category in Classes:
path = os.path.join(datadir, category)
label = Classes.index(category)
for image in os.listdir(path):
try:
image_array = cv2.imread(os.path.join(path,image))
image = cv2.resize(image_array, (IMG_SIZE, IMG_SIZE))
data.append([image, label])
except Exception as e:
pass
```
any alternative suggestions?
Thank you in advance

numpy get elements by array of ranges

I have a data np.array "A" and np.array with ranges[from-to index] "I" to be obtained from A.
How to create a new np array/or list ?
A=[1 161 51 105 143 2 118 127 37 19 4 29 13 136 129 128 129
250 52 53 57 53 49 53 57 49 55 177 84 69 85 210 6 43 128
194 253 0 236 129 131 53 54 56 54 50 48 182 128 52 113 13 169
57 41 233 128 254 160 128 9 81 75 166 89 178 128 128 128 128 128
128 177 128 84 81 84 197 206]
I=[[ 0 2]
[ 2 5]
[ 5 8]
[ 8 14]
...
]
The new array should be like this:
[[1 161 nul] [51 105 143] ... ]
I am not sure why you have a 'null' in one of your intervals. But you can do this using a list comprehension:
import numpy as np
A=np.array([1, 161, 51, 105, 143, 2, 118, 127 , 37, 19, 4 , 29 , 13, 136, 129, 128, 129])
I=[[ 0, 2],
[ 2 ,5],
[ 5 ,8],
[ 8, 14]]
res = [A[i[0]:i[1]] for i in I]
Output:
[array([ 1, 161]),
array([ 51, 105, 143]),
array([ 2, 118, 127]),
array([ 37, 19, 4, 29, 13, 136])]

Issue with matrix slicing in n-deminsional matrix

I was stuck in python function, but later solved it. I have a question regarding the python n-dimensional notation. That matrix was A(2,4,4,3). So what's the difference in accessing the matrix as A[:][0:3, 0:3, 3] and A[:][ 0:3, 0:3 ][3]
Test array(2,4,4,3):
[[[[ 0 1 2] [[[48 49 50]
[ 3 4 5] [51 52 53]
[ 6 7 8] [54 55 56]
[ 9 10 11]] [57 58 59]]
[[12 13 14] [[60 61 62]
[15 16 17] [63 64 65]
[18 19 20] [66 67 68]
[21 22 23]] [69 70 71]]
[[24 25 26] [[72 73 74]
[27 28 29] [75 76 77]
[30 31 32] [78 79 80]
[33 34 35]] [81 82 83]]
[[36 37 38] [[84 85 86]
[39 40 41] [87 88 89]
[42 43 44] [90 91 92]
[45 46 47]]] [93 94 95]]]
With data[0:4, 0:4, 1] you getting each second element from 4x4 array:
[[[ 3 4 5] [[51 52 53]
[15 16 17] [63 64 65]
[27 28 29] [75 76 77]
[39 40 41]] [87 88 89]]]
On the other hand with data[0:4, 0:4][1] you will get second part of 4x4x2 array:
[[[48 49 50]
[51 52 53]
[54 55 56]
[57 58 59]]
[[60 61 62]
[63 64 65]
[66 67 68]
[69 70 71]]
[[72 73 74]
[75 76 77]
[78 79 80]
[81 82 83]]
[[84 85 86]
[87 88 89]
[90 91 92]
[93 94 95]]]

Convert an image to grayscale using only matrix (No BGR2GRAY function) in Python

I'm trying to convert an image to grayscale without using OpenCV or Numpy
Example :
The matrix of my image is
[[[116 116 117]
[115 115 116]
[117 115 115]
...,
[135 138 142]
[137 139 139]
[137 139 139]]
[[116 116 116]
[116 116 116]
[114 116 116]
...,
[135 139 140]
[135 137 138]
[135 137 138]]
[[115 118 114]
[115 118 114]
[112 116 115]
...,
[132 141 141]
[134 137 141]
[133 136 140]]
...,
[[ 35 44 163]
[ 31 40 159]
[ 10 33 158]
...,
[ 14 48 53]
[ 24 56 55]
[ 27 59 58]]
[[ 24 38 156]
[ 19 33 151]
[ 7 28 145]
...,
[ 25 55 66]
[ 15 59 61]
[ 17 61 63]]
[[ 0 27 131]
[ 0 26 130]
[ 0 34 113]
...,
[ 11 39 55]
[ 6 28 56]
[ 4 26 54]]]
Using the cv2.COLOR_BGR2GRAY function the matrix is :
[[150 150 150 ..., 150 150 150]
[150 173 175 ..., 97 91 89]
[150 176 179 ..., 95 89 82]
...,
[150 66 67 ..., 152 154 152]
[150 62 59 ..., 152 152 152]
[150 62 64 ..., 155 154 151]]
First, i don't get why it returns a 36 integers when i gave 108 and how can i do it manually
Thanks for your help :)
Question 1
You are getting 36 integers instead of 108 because your original image had 3 channels (red, green, blue, a.k.a RGB). When you convert it to grayscale, you are flattening it to only one channel. 108 / 3 = 36, seems legit!
Quesion 2
Converting it by hand: There are multiple ways to convert an RGB image to grayscale, but the most straightforward would be to take the average of the three channels, basically (red_values + green_values + blue values) / 3. So take your original image array, and run:
gray_image = (image[:,:,0] + image[:,:,1] + image[:,:,2]) / 3
The above is assuming that your image array is in the form image.shape = (pixel_height, pixel_width, number_of_channels), and that the first 3 channels represent your R,G, and B channels but that's pretty standard

Categories