I am new to R and would like to use it for my data analysis and visualization.
I have a dataframe with about 38575 rows (pixels) and 600 columns. Each column contains the intensity of an analyte, resulting in a spectrum per pixel.
I also have x and y coordinates for each pixel to create a data cube(array), in the sense that if I say image_cube[1,1,] gives me the first spectrum and if I say image_cube[,,1], I get an image of all pixels showing the intensity for the first analyte.
Not all pixels have a spectrum and they are not in the dataframe, these should just be empty pixels (black).
EDIT
I tried to use the following code with ROI data being the big dataframe and sample_overview the variable containing x and y coordinates for each pixel:
ROI_cube <- array(rep(0, 311*381*603), dim=c(311, 381, 603))
for (i in 1:dim(ROI_data)[1]) {
ROI_cube[sample_overview[i,2], sample_overview[i,1],] = ROI_data[i,]
}
But I get the following error:
Error in ROI_cube[sample_overview[i, 1], sample_overview[i, 2], ] <- ROI_data[i, :
incorrect number of subscripts
If i get your question correctly you want to map a 2D Dataframe of Spectra through known x-y Coordinates to a 3D-Array.
If thats all you want, you don't need any packages, it's just a matter of mapping the data in the dataframe to an Array
#Simulate some gaussian spectra
set.seed(1234)
simSpec <- function()
{
x <- 1:400
y <- stats::dnorm(x,mean=runif(1,min=0,max=400),sd=runif(1,min=2,max=50))
return(y)
}
#build a dataframe
data <- data.frame(matrix(data=NA,nrow=400,ncol=20))
for(i in 1:20) data[,i] <- simSpec()
#assume data is ordered in ascending x/y pixels
#=> data[,1] -> x=1, y=1 ; data[,2] -> x=2, y=1; data[,length(x)] -> x=length(x), y=y;
#data[,m+(n-1)*length(x)] -> x=m, y=n
Array <- array(data=t(data),dim=c(5,4,400)) #Build Array of format [X,Y,NSpectralVariables]
#transpose dataframe because default order is to first increase Columnnumber
plot(Array[1,1,],type="l") # Plot Spectrum at x=1, y=1
contour(Array[,,1]) #Contour Intensity at first Analyte
Related
I am trying to manually convert a BGR image to HSV. I need to find the maximum pixel value each of 3 image channels (numPy arrays) and create a new array which contains the maximum of the 3 channels.
def convertBGRtoHSV(image):
# normalize image
scaledImage = image // 256
# split image into 3 channels
B, G, R = cv2.split(scaledImage)
# find the shape of each array
heightB, widthB = B.shape
V = []
for h_i in range(0, height):
for w_i in range(0, width):
V[h_i][w_i] = max(B[h_i][w_i], G[h_i][w_i], R[h_i][w_i])
I am getting this error: IndexError: list index out of range
I know this loop is incorrect. I know to access the value of a pixel in an array you must say the location as such as x[:,:] but I am not sure how to loop over all the pixels of each image and make a new array with the max value of each array element.
If possible I would like to know how to use a numPy "Vectorized Operation" to accomplish this as well as the for loop.
There is a builtin function for element-wise maximum:
V = np.maximum(np.maximum(R, G), B)
... and you are done
Following up on my comment:
import cv2
import numpy as np
image = cv2.imread(image)
height, width, _ = image.shape
# initialize your output array 'v'
v = np.zeros((height, width))
# loop over each index in ranges dictated by the image shape
for row in range(height):
for col in range(width):
# assign the maximum value across the 3rd dimension (color channel)
# from the original image to your output array
v[row, col] = max(image[row, col, :])
The size of two Numpy array are:
(406, 278)
(406,)
however, error occurred while appending Numpy array:
ValueError: all the input arrays must have same number of dimensions
code:
y = numpy.array(kmeans.labels_,copy=True)
x = numpy.append(x, y, axis=1); #error
x = numpy.append(x, y, axis=0); #error
As the error says, you are trying to append a 1d array to a 2d array with an axis parameter, and according to docs:
When axis is specified, values must have the correct shape.
You need to reshape y to a 2d array firstly:
Both of these two methods should work:
np.append(x, y[None, :], axis=0)
np.append(x, y.reshape(1,-1), axis=0)
According to numpy documentation ,
When axis is specified, values must have the correct shape.
So if you want to append the vector y = [0 1 2] to the matrix x = [[0, 0],[1, 1],[2, 2]] with axis=1, first you need to turn y into a matrix form, and then transpose it:
x = numpy.zeros((406,278))
y = numpy.zeros((406,))
x = numpy.append(x, numpy.transpose([y]), axis=1);
print(x.shape) # gives (406,279)
I am trying to do some numpy matrix math because I need to replicate the repmat function from MATLAB. I know there are a thousand examples online, but I cannot seem to get any of them working.
The following is the code I am trying to run:
def getDMap(image, mapSize):
newSize = (float(mapSize[0]) / float(image.shape[1]), float(mapSize[1]) / float(image.shape[0]))
sm = cv.resize(image, (0,0), fx=newSize[0], fy=newSize[1])
for j in range(0, sm.shape[1]):
for i in range(0, sm.shape[0]):
dmap = sm[:,:,:]-np.array([np.tile(sm[j,i,:], (len(sm[0]), len(sm[1]))) for k in xrange(len(sm[2]))])
return dmap
The function getDMap(image, mapSize) expects an OpenCV2 HSV image as its image argument, which is a numpy array with 3 dimensions: [:,:,:]. It also expects a tuple with 2 elements as its imSize argument, of course making sure the function passing the arguments takes into account that in numpy arrays the rows and colums are swapped (not: x, y, but: y, x).
newSize then contains a tuple containing fracions that are used to resize the input image to a specific scale, and sm becomes a resized version of the input image. This all works fine.
This is my goal:
The following line:
np.array([np.tile(sm[i,j,:], (len(sm[0]), len(sm[1]))) for k in xrange(len(sm[2]))]),
should function equivalent to the MATLAB expression:
repmat(sm(j,i,:),[size(sm,1) size(sm,2)]),
This is my problem:
Testing this, an OpenCV2 image with dimensions 800x479x3 is passed as the image argument, and (64, 48) (a tuple) is passed as the imSize argument.
However when testing this, I get the following ValueError:
dmap = sm[:,:,:]-np.array([np.tile(sm[i,j,:], (len(sm[0]),
len(sm[1]))) for k in xrange(len(sm[2]))])
ValueError: operands could not be broadcast together with
shapes (48,64,3) (64,64,192)
So it seems that the array dimensions do not match and numpy has a problem with that. But my question is what? And how do I get this working?
These 2 calculations match:
octave:26> sm=reshape(1:12,2,2,3)
octave:27> x=repmat(sm(1,2,:),[size(sm,1) size(sm,2)])
octave:28> x(:,:,2)
7 7
7 7
In [45]: sm=np.arange(1,13).reshape(2,2,3,order='F')
In [46]: x=np.tile(sm[0,1,:],[sm.shape[0],sm.shape[1],1])
In [47]: x[:,:,1]
Out[47]:
array([[7, 7],
[7, 7]])
This runs:
sm[:,:,:]-np.array([np.tile(sm[0,1,:], (2,2,1)) for k in xrange(3)])
But it produces a (3,2,2,3) array, with replication on the 1st dimension. I don't think you want that k loop.
What's the intent with?
for i in ...:
for j in ...:
data = ...
You'll only get results from the last iteration. Did you want data += ...? If so, this might work (for a (N,M,K) shaped sm)
np.sum(np.array([sm-np.tile(sm[i,j,:], (N,M,1)) for i in xrange(N) for j in xrange(M)]),axis=0)
z = np.array([np.tile(sm[i,j,:], (N,M,1)) for i in xrange(N) for j in xrange(M)]),axis=0)
np.sum(sm - z, axis=0) # let numpy broadcast sm
Actually I don't even need the tile. Let broadcasting do the work:
np.sum(np.array([sm-sm[i,j,:] for i in xrange(N) for j in xrange(M)]),axis=0)
I can get rid of the loops with repeat.
sm1 = sm.reshape(N*M,L) # combine 1st 2 dim to simplify repeat
z1 = np.repeat(sm1, N*M, axis=0).reshape(N*M,N*M,L)
x1 = np.sum(sm1 - z1, axis=0).reshape(N,M,L)
I can also apply broadcasting to the last case
x4 = np.sum(sm1-sm1[:,None,:], 0).reshape(N,M,L)
# = np.sum(sm1[None,:,:]-sm1[:,None,:], 0).reshape(N,M,L)
With sm I have to expand (and sum) 2 dimensions:
x5 = np.sum(np.sum(sm[None,:,None,:,:]-sm[:,None,:,None,:],0),1)
len(sm[0]) and len(sm[1]) are not the sizes of the first and second dimensions of sm. They are the lengths of the first and second row of sm, and should both return the same value. You probably want to replace them with sm.shape[0] and sm.shape[1], which are equivalent to your Matlab code, although I am not sure that it will work as you expect it to.
I have 100 points representing the boundary of a sphere of radius .1 and center (.5,.5,.5). I would like to represent this sphere in an array of points on a 3-D gird. The values of the array would be binary. 1 to represent inside the sphere and 0 to represent outside the sphere. The representation would be upon the unit cube.
I forsee the array looking something like this. For an array 100 by 100 by 100. The (1,1,1) value would be 0. The (50,50,50) value would be 1, since this grid point is inside the sphere.
Here is the code that creates and plots the 100 (or more) points. These points all lay on the boundary of the sphere.
library(scatterplot3d)
n <- 100
r <- rep(.1,n)
theta <- runif(n,0,pi)
phi <- runif(n,0,2*pi)
x <- r*sin(theta)*cos(phi)+.5
y <- r*sin(theta)*sin(phi)+.5
z <- r*cos(theta)+.5
graphic <- scatterplot3d(x,y,z,xlim=c(0,1),ylim=c(0,1),zlim=c(0,1))
Maybe this helps you on your way. I'm guessing that visualization is no the main objective here, but I've included a series of image plots to show the sections of the 3d array.
Example:
n=25
cen <- c(0.5,0.5,0.5)
rad <- 1
xs <- seq(cen[1]-rad,cen[1]+rad,,n)
ys <- seq(cen[2]-rad,cen[2]+rad,,n)
zs <- seq(cen[3]-rad,cen[3]+rad,,n)
grd <- expand.grid(x=xs, y=ys, z=zs)
a <- array(0, dim=c(n,n,n))
for(i in seq(a)){
a[i] <- as.numeric(dist(rbind(grd[i,], cen)) <= rad)
}
png("sections.png", units="in", width=10, height=4, res=400)
op <- par(mfrow=c(1,n), mar=rep(0.1,4))
for(i in seq(n)){
image(x=xs, y=ys, z=a[,,i], col=c("white", "black"), axes=FALSE, xlab="", ylab="")
abline(h=xs, col=8, lwd=0.2)
abline(v=ys, col=8, lwd=0.2)
#box()
}
par(op)
dev.off()
n <- 3
x <- 1:n
y <- 1:n
z <- 1:n
grid <- expand.grid(x,y,z)
vec <- ((grid[,1]-rep(n/2+.5,n^3))^2 +
(grid[,2]-rep(n/2+.5,n^3))^2 +
(grid[,3]-rep(n/2+.5,n^3))^2)^.5
a <- array(round(vec,3),dim=c(n,n,n)) #in array (pixel) scale
a.metric <- a*(1/n) #in "metric" scale
a
a.metric
STACK <- array(as.numeric(a.metric <=.1),dim=c(n,n,n))
STACK
I have searched for an answer for my question on here but cannot find one, so I apologize in advance if it already exists!
What I am trying to do is create a 3D array of 3-d points in space (x,y,z). I know in a 1D vector you can specify the interval, like 1:5:20, to get a vector from 1 to 20 spaced by 5. What I would like to do is create a 3D array, most likely row by row would be the most efficient, where the spacing is by a unit vector (ix, iy, iz). so, for example,
a(1,1,:) = [1, 1, 1]
uv = [0.5 0.5 0.5]
a(2,2,:) = [1.5, 1.5, 1.5]
etc. I know the numbers are not 'unit vectors', but the idea is there. Is there something along the lines of a = [1, 1, 1] : uv : [end, end, end] ???
You might be interested in a mesh grid.
An example:
[X,Y,Z] = meshgrid(1:0.1:2, 1:0.1:2, 1:0.1:2); %# they can be different
points = [X(:) Y(:) Z(:)];
plot3(points(:,1),points(:,2),points(:,3),'.')
box on, axis equal
xlabel x, ylabel y, zlabel z