Suppose I have original_image: as (451, 521, 3) shape.
And it contains [0,0,0] RGB values at some locations.
I would like to replace all [0,0,0] with [0,255,0]
What I tried was
I created mask which has True where [0,0,0] are located in original_image
And that mask has (451, 521) shape
I thought I could use following
new_original_image=original_image[mask]
But it turned out new_original_image is just an array (shape is like (18, 3)) whose all elements (for example, [[ 97 68 108],[127 99 139],[156 130 170],...]) are filtered by True of mask array from original_image
Here is one way
idx=np.all(np.vstack(a)==np.array([0,0,5]),1)
a1=np.vstack(a)
a1[idx]=[0,0,0]
yourary=a1.reshape(2,-1,3)
Out[150]:
array([[[0, 0, 0],
[0, 0, 1],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 1],
[0, 0, 0],
[0, 0, 0]]])
Data input
a
Out[133]:
array([[[0, 0, 0],
[0, 0, 1],
[0, 0, 5],
[0, 0, 5]],
[[0, 0, 0],
[0, 0, 1],
[0, 0, 5],
[0, 0, 5]]])
I would like to replace all [0,0,0] with [0,255,0]
import cv2
img = cv2.imread("test.jpg")
rows, cols, channels = img.shape
for r in range(rows):
for c in range(cols):
if np.all(img[r,c][0]==[0,0,0]):
img[r,c]=[0,255,0]
Based on reply solution from Wen-Ben, I try to write detailed code snippet that I wanted to implement
# original_image which contains [0,0,0] at several location
# in 2 (last) axis from (451, 521, 3) shape image
# Stack original_image or using original_image.reshape((-1,3)) is also working
stacked=np.vstack(original_image)
# print(stacked.shape)
# (234971, 3)
# Create mask array which has True where [0,0,0] are located in stacked array
idx=np.all(stacked==[0,0,0],1)
# print(idxs.shape)
# (234971,)
# Replace existing values which are filtered by idx with [0,255,0]
stacked[idx]=[0,255,0]
# Back to original image shape
original_image_new=stacked.reshape(original_image.shape[0],original_image.shape[1],3)
# print(original_image_new.shape)
# (451, 521, 3)
Related
So I'm using Keras generator to get data augmented for image segmentation
I have a specific mask which each set of pixel represent a region of my masks, so I must have a range of pixel that contains 11 classes (0 and 255 and 191).
The problem with Keras generator that he is changing the range of pixel.
so I want to detect images that pixel intensity are not equal to my specific classes (pixel range) (255,56,...) and try to delete them from my dataset but im always getting errors.
Y_train : numpy array that contains all the masks
Y_train = array([[[[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
...,
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
...,
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
...,
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]]], dtype=uint8)
I tried this 1st attempt :
for i in range(len(Y_train)):
if Y_train[i] != 255 and Y_train[i] !=56 and Y_train[i] !=137 and Y_train[i] !=26 :
print ('index',i)
Second one :
for i in range (len(Y_train)):
if Y_train[i][Y_train[i] != (0 and 255 and 56 and 137 and 26 and 87 and 112 and 191 and 212 and 164 and 229 and 244 )] :
print('index 0',i)
Third one :
for i in range(len(Y_train)):
if (Y_train[I] != 255 and Y_train[i] !=56 and Y_train[i] !=137)).all() : print('index 0',i)
PS : Sorry for my English
I think first of all you must change the "and" with "or"; then, are you sure y_train[i] returns an integer value? please double check the type of y_train[i] or y_train itself and try to search its elements
Your Y_train array looks like and rgb matrices list. ie Y_train has 4 dimensions.
when you index Y_train[i] you get and 3 dimension matrix, if you compare this with a escalar number like 255, then you get the same 3 dimension matrix with True or False (True where there was an 255 and False otherwise), therefore to compare this boolean matrices you need to use any() or all().
Therefore you should rethink your code, because this way does not seem efficient
I am finding the lowest value in the array "value" using a min function. The lowest value is assigned a 1, all else 0. I have several descriptive column variables: drug, size, strength, form, time. I want to find the min value of each unique key rather than the lowest value in the entire array "value".
I have tried running loops for each column variable.
def min_mask(arr):
m = np.min(arr)
return np.vectorize(lambda x: x == m)(arr).astype(int)
if __name__ == '__main__':
my_arr = np.array(meltDF["value"])
print(min_mask(my_arr))
There are many options here, for example:
1) Pre-initialize the mask and use argmin to fill in the appropriate places:
arr = np.random.rand(10, 4)
indices = np.argmin(arr, axis=0)
mask = np.zeros_like(arr, dtype=np.int)
mask[indices, range(len(indices))] = 1
2) Using apply_along_axis is probably the style you prefer:
def is_minimum(v):
return v == np.min(v)
mask = np.apply_along_axis(is_minimum, axis=0, arr=arr).astype(np.int)
These solutions assume that each column corresponds to a unique key.
You can compare elements to their column-wise mins, then case to uint8 to save a bit of space:
>>> import numpy as np
>>> np.random.seed(444)
>>> arr = np.random.rand(10, 4)
>>> (arr == arr.min(axis=0)).astype(np.uint8)
array([[0, 0, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 1, 0, 0],
[0, 0, 1, 0]], dtype=uint8)
Because of NumPy's broadcasting, the comparison arr == arr.min(axis=0) will produce a result that is the same shape of arr, even though arr.min(axis=0) will have shape (4,).
Note that if columns have duplicate minimums, this may generate more than one "1" in a single column.
I am working on a piece of python code that will take in an image in grey scale, scale it, and output a 3d model with the height of each pixel being determined by the value of the grey scale. I have everything working except the output of the 3d model. I am using numpy-stl to create it based on an array of values derived from the image. Using the numpy-stl library I create a box and then copy it as many times as i need for the image. then I translate each one to the position and height corresponding with the image. This all works. The problem comes when I try to save it all as one .stl file. I cant figure out how to combine all the individual meshes of the cubes into one.
Here is just the code dealing with the creation of the 3d array. I can plot the created meshes but not save them.
from stl import mesh
import math
import numpy
test = [[1,2],[2,1]]
a = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]]
# Create 6 faces of a cube, 2 triagles per face
data = numpy.zeros(12, dtype=mesh.Mesh.dtype)
#cube defined in stl format
# Top of the cube
data['vectors'][0] = numpy.array([[0, 1, 1],
[1, 0, 1],
[0, 0, 1]])
data['vectors'][1] = numpy.array([[1, 0, 1],
[0, 1, 1],
[1, 1, 1]])
# Right face
data['vectors'][2] = numpy.array([[1, 0, 0],
[1, 0, 1],
[1, 1, 0]])
data['vectors'][3] = numpy.array([[1, 1, 1],
[1, 0, 1],
[1, 1, 0]])
# Left face
data['vectors'][4] = numpy.array([[0, 0, 0],
[1, 0, 0],
[1, 0, 1]])
data['vectors'][5] = numpy.array([[0, 0, 0],
[0, 0, 1],
[1, 0, 1]])
# Bottem of the cube
data['vectors'][6] = numpy.array([[0, 1, 0],
[1, 0, 0],
[0, 0, 0]])
data['vectors'][7] = numpy.array([[1, 0, 0],
[0, 1, 0],
[1, 1, 0]])
# Right back
data['vectors'][8] = numpy.array([[0, 0, 0],
[0, 0, 1],
[0, 1, 0]])
data['vectors'][9] = numpy.array([[0, 1, 1],
[0, 0, 1],
[0, 1, 0]])
# Left back
data['vectors'][10] = numpy.array([[0, 1, 0],
[1, 1, 0],
[1, 1, 1]])
data['vectors'][11] = numpy.array([[0, 1, 0],
[0, 1, 1],
[1, 1, 1]])
# Generate 4 different meshes so we can rotate them later
meshes = [mesh.Mesh(data.copy()) for _ in range(16)]
#iterates through the array and translates cube in the x and y direction according
#to position in array and in the z direction according to eh value stored in the array
def ArrayToSTL(array, STLmesh):
y_count = 0
x_count = 0
count = 0
for row in array:
x_count = 0
for item in row:
meshes[count].x += x_count
meshes[count].y += y_count
meshes[count].z += item
x_count +=1
count += 1
y_count += 1
ArrayToSTL(a, meshes)
# Optionally render the rotated cube faces
from matplotlib import pyplot
from mpl_toolkits import mplot3d
# Create a new plot
figure = pyplot.figure()
axes = mplot3d.Axes3D(figure)
# Render the cube faces
for m in meshes:
axes.add_collection3d(mplot3d.art3d.Poly3DCollection(m.vectors))
# Auto scale to the mesh size
scale = numpy.concatenate([m.points for m in meshes]).flatten(-1)
axes.auto_scale_xyz(scale, scale, scale)
# Show the plot to the screen
pyplot.show()
This works well:
import numpy as np
import stl
from stl import mesh
import os
def combined_stl(meshes, save_path="./combined.stl"):
combined = mesh.Mesh(np.concatenate([m.data for m in meshes]))
combined.save(save_path, mode=stl.Mode.ASCII)
loading stored stl files and meshing them, use this.
direc = "path_of_directory"
paths = [os.path.join(direc, i) for i in os.listdir(direc)]
meshes = [mesh.Mesh.from_file(path) for path in paths]
combined_stl(meshes)
I'm attempting to slice a 3-D instance of ndarray representing a color image, where each element (or pixel) in the 2-D array contains an array with 3 bytes corresponding to the values of Red, Green, and Blue respectively. I want to slice out a 2-D ndarray for each color individually so that I can flatten them and concatenate them end-to-end as per our implementation requirements. The code I'm currently trying is...
red = image[:, :, 0]
green = image[:, :, 1]
blue = image[:, :, 2]
collapsed_image = numpy.concatenate((red.flatten('C'), green.flatten('C'), blue.flatten('C')), axis=0)
Where image is my numpy.ndarray object containing the 3-D array of bytes. Would this work to slice out each individual color's 2-D array and flatten/concatenate them together end-to-end?
Do you mean to achieve an output like this?
from scipy.ndimage import *
import matplotlib.pyplot as p
%matplotlib inline
im=imread('rgb.png')
print np.shape(im)
p.subplot(121)
p.imshow(im)
red = im[:, :, 0]
green = im[:, :, 1]
blue = im[:, :, 2]
imchannels = np.concatenate((red, green, blue))
p.subplot(122)
p.imshow(imchannels)
Output:
(215L, 235L, 3L)
an ndarray is already a flatten collection of bytes of memory, but not always in the desired order. np.rollaxis can modify it.
As a simple example :
First a classic 2x2 image (each digit is associated to a canal):
image=np.arange(12).reshape(2,2,3)%3
In [08]: image
Out[08]:
array([[[0, 1, 2],
[0, 1, 2]],
[[0, 1, 2],
[0, 1, 2]]], dtype=int32)
An other view, canal first :
bycolor= r,g,b = np.rollaxis(image,axis=2)
In [10]: bycolor
Out[10]:
array([[[0, 0],
[0, 0]],
[[1, 1],
[1, 1]],
[[2, 2],
[2, 2]]], dtype=int32)
and flattened layouts :
In [11]: image.flatten()
Out[11]: array([0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2], dtype=int32)
In [12]: bycolor.flatten()
Out[12]: array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], dtype=int32)
I think the last is what you want : np.rollaxis(image,2).flatten()
I'm working with DICOM files that contain image data. I am using pydicom to read the metadata from the .DCM file. Now, the pixel data that is extracted from the .DCM file is returned as a 2 dimensional numpy ndarray.
The particular DICOM files I am working with save a single intensity value per pixel. After I perform some manipulation on them I end up with a single floating point value (between 0.0 and 1.0) per pixel in a 2 dimensional ndarray:
[
[ 0.98788927, 0.98788927 0.98788927, ..., 0.88062284 0.89532872 0.87629758],
[ 0.98788927, 0.98788927, 0.98788927, ..., 0.8884083, 0.89446367, 0.87889273],
[ 0.98788927, 0.98788927, 0.98788927, ..., 0.89100346, 0.89532872, 0.87629758],
,...,
[ 0.97491349, 0.97491349, 0.97491349, ..., 0.74480969, 0.72318339, 0.73269896],
[ 0.97491349, 0.97491349, 0.97491349, ..., 0.74913495, 0.74480969, 0.74740484],
[ 0.97491349, 0.97491349, 0.97491349, ..., 0.74913495 0.75865052, 0.75086505],
]
I would like to transform this into a 3-D ndarray with numpy by replacing each element with a sequence of elements [R, G, B] where R=G=B=intensity value.
The ndarray.put() function flattens out the matrix which rules out that method.
I also tried:
for x in range( len(a[0]) ):
for y in range( len(a) ):
a[x][y] = [ a[x][y], a[x][y], a[x][y] ]
but get a
ValueError: setting an array element with a sequence.
Suggestions? I'm trying to keep data manipulation as light as possible because some of these images are huge, so I want to avoid a hack/manually copying all the data to a separate variable.
Thanks in advance for any help.
So what you want, of course, is an array of shape m x n x r, where r is the tuple size.
One way to do this, which seems to me the most straightforward, is to: (i) explicitly create a 3D grid array, identical to your original 2D arrayexcept for addition of the last dimension, r, which has been added, and then; (ii) map your rgb tuples onto this Grid.
>>> # first, generate some fake data:
>>> m, n = 5, 4 # rows & cols, represents dimensions of original image
>>> D = NP.random.randint(0, 10, m*n).reshape(m, n)
>>> D
array([[8, 2, 2, 1],
[7, 5, 0, 9],
[2, 2, 9, 3],
[5, 7, 3, 0],
[5, 8, 1, 7]])
Now create the Grid array:
>>> G = NP.zeros((m, n, r), dtype='uint')
Think of G as an m x n rectangular grid--same as D--but with each of the 20 cells storing not an integer (like D) but an rgb tuple, so:
>>> # placing the color pixel (209, 127, 87) at location 3,2:
>>> G[3,2] = (209, 124, 87)
To grok this construction, you can see the rgb tuple w/in the Grid, G, by looking at three consecutive slices of G:
>>> G[:,:,0] # red
>>> array([[ 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0],
[ 0, 0, 209, 0, 0],
[ 0, 0, 0, 0, 0]], dtype=uint8)
>>> G[:,:,1] # green
>>> array([[ 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0],
[ 0, 0, 124, 0, 0],
[ 0, 0, 0, 0, 0]], dtype=uint8)
>>> G[:,:,2] # blue
>>> array([[ 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0],
[ 0, 0, 87, 0, 0],
[ 0, 0, 0, 0, 0]], dtype=uint8)
Now to actually get the result you want, we just need to (i) create a grid, G, a 3D NumPy array, whose first two dimensions are taken from the array stored in your .DCM file, and whose third dimension is three, from the length of an rgb tuple; then (ii) map the rgb tuples onto that grid, G.
>>> # create the Grid
>>> G = NP.zeros((m, n, r), dtype='uint')
>>> # now from the container that holds your rgb tuples, create *three* m x n arrays,
>>> # one for each item in your rgb tuples
>>> # now just map the r values (1st itm in each rgb tuple) to the 3D grid
>>> G[:,:,0] = r_vals
>>> G[:,:,1] = g_vals
>>> G[:,:,2] = b_vals
>>> G.shape
(5, 4, 3)