Siemens CT dose report/patient protocol PixelData - python

I’m trying to extract dicom PixelData from Siemens’ dose report but it contains only zeros. With GE dose report I read the data without a trouble with pydicom or simpleITK. Any ideas why siemens report contains only zeros?
Thanks!
Came this far, but characters are a mess, I don't know what else to do.
import dicom
import numpy as np
import matplotlib.pyplot as plt
f="patient-protocol.dcm"
ds=dicom.read(f)
overlay_px_data = ds[0x6000, 0x3000].value
rows = ds[0x6000, 0x0010].value
cols=ds[0x6000, 0x0011].value
arr=np.fromstring(overlay_px_data, dtype="uint8")
arr=np.unpackbits(arr)
arr=np.reshape(arr, (rows, cols))
plt.imshow(arr, cmap="gray")
plt.show()
dose-image

i_overlay = 1
n_bits = 8
# On (60xx,3000) are stored ovelays.
# First is (6000,3000), second (6002,3000), third (6004,3000),
# and so on.
dicom_tag1 = 0x6000 + 0*i_overlay
overlay_raw = data[0x6000,0x3000].value
# On (60xx,0010) and (60xx,0011) is stored overlay size
rows = data[0x6000,0x0010].value # rows = 512
cols = data[0x6000,0x0011].value # cols = 512
decoded_linear = np.zeros(len(overlay_raw)*n_bits)
# Decoding data. Each bit is stored as array element
for i in range(1,len(overlay_raw)):
for k in range (0,n_bits):
byte_as_int = overlay_raw[i]
decoded_linear[i*n_bits + k] = (byte_as_int >> k) & 0b1
overlay = np.reshape(decoded_linear,[rows,cols])
plt.imshow(overlay)
plt.show()
Found the solution for now. Edited a code a bit (removed ord()), a numpy decoding solution would be great/better.
code source link

Related

How to manipulate image bands as arrays of numbers

I'm new to Python, and I'm trying to deconstruct image bands as arrays of numbers by applying the Singular Value Decomposition (SVD) to them and then putting them back together with matplotlib.image and the Image module from PIL. An SVD may also be written as a sum of dyads s1u1v1T + ... + sKuKvKT, and the point in decomposing it in this way is that a near-perfect approximation of the image can be made from just a few of those dyads, so less data is required.
There must be something wrong with the calculation, though because result_r, result_g, and result_b look like this when converted to Images, and new_image looks like this.
For an example of what this should look like, here are the first dyads of the layers of this image. The image that I'm using (April23.jpg) is this.
import matplotlib.image as image
import numpy.linalg as la
import numpy as np
from PIL import Image
def getcolumn(j, m):
col = []
for i in range(len(m)):
col.append(m[i][j])
return col
def extractCols(U):
Ucols = []
for j in range(len(U[0])):
Ucols.append(getcolumn(j, U))
return np.asarray(Ucols)
def vectorMultiply(u, v):
matrix = []
for i in range(len(u)):
newVec = []
for j in range(len(v)):
newVec.append(u[i] * v[j])
matrix.append(newVec)
return np.asarray(matrix)
im = Image.open('C:/Users/<user>/Desktop/img/April23.jpg')
im.load()
sim = Image.Image.split(im)
rsim = sim[0].save("rsim.jpg") # image bands as images
gsim = sim[1].save("gsim.jpg")
bsim = sim[2].save("bsim.jpg")
# image bands as arrays of numbers
arsim = image.imread('C:/Users/<user>/Desktop/img/rsim.jpg')
agsim = image.imread('C:/Users/<user>/Desktop/img/gsim.jpg')
absim = image.imread('C:/Users/<user>/Desktop/img/bsim.jpg')
ur, sr, vhr = la.svd(arsim, False) # SVD on each band
ug, sg, vhg = la.svd(agsim, False)
ub, sb, vhb = la.svd(absim, False)
urcols = extractCols(ur)
ugcols = extractCols(ug)
ubcols = extractCols(ub)
# calculating the first dyads
result_r = np.multiply(sr[0], vectorMultiply(urcols[0], vhr[0]))
result_g = np.multiply(sg[0], vectorMultiply(ugcols[0], vhg[0]))
result_b = np.multiply(sb[0], vectorMultiply(ubcols[0], vhb[0]))
r = Image.fromarray(result_r, "L")
g = Image.fromarray(result_g, "L")
b = Image.fromarray(result_b, "L")
new_image = Image.merge("RGB", (r, g, b))
What am I missing, here? It seems to be something with the calculations. I figured for a matrix one would have to extract the columns, say the column [1, 2, 3] from a matrix [[1,...], [2,...], [3,...]], since each element of the matrix is a row. So, I wrote extractCols() for that. numpy's matrix add and multiply seem to be fine. I wrote vectorMultiply because np.dot(), np.multiply(), and np.matmul() didn't seem to realize that u was a column and kept saying the dimensions didn't match up. I tested it and it seemed to do what I wanted it to. I was also thinking that maybe the "rows" of U are actually the columns already and don't need to be extracted, but that didn't work either. I've also tried not using np.asarray() without any luck.
Any advice is appreciated.

gee 'sampleRectangle()' returning 1x1 array

I'm facing an issue when trying to use 'sampleRectangle()' function in GEE, it is returning 1x1 arrays and I can't seem to find a workaround. Please, see below a python code in which I'm using an approach posted by Justin Braaten. I suspect there's something wrong with the geometry object I'm passing to the function, but at the same time I've tried several ways to check how this argument is behaving and couldn't no spot any major issue.
Can anyone give me a hand trying to understand what is happening?
Thanks!
import json
import ee
import numpy as np
import matplotlib.pyplot as plt
ee.Initialize()
point = ee.Geometry.Point([-55.8571, -9.7864])
box_l8sr = ee.Geometry(point.buffer(50).bounds())
box_l8sr2 = ee.Geometry.Polygon(box_l8sr.coordinates())
# print(box_l8sr2)
# Define an image.
# l8sr_y = ee.Image('LANDSAT/LC08/C01/T1_SR/LC08_038029_20180810')
oli_sr_coll = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
## Function to mask out clouds and cloud-shadows present in Landsat images
def maskL8sr(image):
## Bits 3 and 5 are cloud shadow and cloud, respectively.
cloudShadowBitMask = (1 << 3)
cloudsBitMask = (1 << 5)
## Get the pixel QA band.
qa = image.select('pixel_qa')
## Both flags should be set to zero, indicating clear conditions.
mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0)
mask = qa.bitwiseAnd(cloudsBitMask).eq(0)
return image.updateMask(mask)
l8sr_y = oli_sr_coll.filterDate('2019-01-01', '2019-12-31').map(maskL8sr).mean()
l8sr_bands = l8sr_y.select(['B2', 'B3', 'B4']).sampleRectangle(box_l8sr2)
print(type(l8sr_bands))
# Get individual band arrays.
band_arr_b4 = l8sr_bands.get('B4')
band_arr_b3 = l8sr_bands.get('B3')
band_arr_b2 = l8sr_bands.get('B2')
# Transfer the arrays from server to client and cast as np array.
np_arr_b4 = np.array(band_arr_b4.getInfo())
np_arr_b3 = np.array(band_arr_b3.getInfo())
np_arr_b2 = np.array(band_arr_b2.getInfo())
print(np_arr_b4.shape)
print(np_arr_b3.shape)
print(np_arr_b2.shape)
# Expand the dimensions of the images so they can be concatenated into 3-D.
np_arr_b4 = np.expand_dims(np_arr_b4, 2)
np_arr_b3 = np.expand_dims(np_arr_b3, 2)
np_arr_b2 = np.expand_dims(np_arr_b2, 2)
# # print(np_arr_b4.shape)
# # print(np_arr_b5.shape)
# # print(np_arr_b6.shape)
# # Stack the individual bands to make a 3-D array.
rgb_img = np.concatenate((np_arr_b2, np_arr_b3, np_arr_b4), 2)
# print(rgb_img.shape)
# # Scale the data to [0, 255] to show as an RGB image.
rgb_img_test = (255*((rgb_img - 100)/3500)).astype('uint8')
# plt.imshow(rgb_img)
plt.show()
# # # create L8OLI plot
# fig, ax = plt.subplots()
# ax.set(title = "Satellite Image")
# ax.set_axis_off()
# plt.plot(42, 42, 'ko')
# img = ax.imshow(rgb_img_test, interpolation='nearest')
I have the same issue. It seems to have something to do with .mean(), or any reduction of image collections for that matter.
One solution is to reproject after the reduction. For example, you could try adding "reproject" at the end:
l8sr_y = oli_sr_coll.filterDate('2019-01-01', '2019-12-31').map(maskL8sr).mean().reproject(crs = ee.Projection('EPSG:4326'), scale=30)
It should work.

letters in emnist training dataset are rotated and little vague

I am using emnist-letters-train-images-idx3-ubyte.gz and emnist-letters-train-labels-idx1-ubyte.gz from http://biometrics.nist.gov/cs_links/EMNIST/gzip.zip
I wrote this little script to see images
import os
import struct
import numpy as np
import scipy.misc
np.set_printoptions(threshold='nan')
path = './'
fname_img = os.path.join(path, 'emnist-letters-train-images-idx3-ubyte')
fname_lbl = os.path.join(path, 'emnist-letters-train-labels-idx1-ubyte')
with open(fname_lbl, 'rb') as flbl:
magic, num = struct.unpack(">II", flbl.read(8))
lbl = np.fromfile(flbl, dtype=np.int8)
with open(fname_img, 'rb') as fimg:
magic, num, rows, cols = struct.unpack(">IIII", fimg.read(16))
img = np.fromfile(fimg, dtype=np.uint8).reshape(len(lbl), rows, cols)
print 'image',img.shape
print 'label',lbl.shape
labels, indices = np.unique(lbl,return_index=True)
print 'unique labels',labels
print 'unique indices',indices
for i in indices:
image = img[i]
for y in image:
row = ""
for x in y:
row += '{0: <4}'.format(x)
print row
print 'label',lbl[i],'\n'
newfilename = str(lbl[i]) + '.jpg'
scipy.misc.imsave(newfilename, image)
Here is the output image
My question is that - i and l are undifferentiable , r is unrecognizable , ,many letters are inverted . Why is that ?
Thanks.
Flip the image horizontally and then rotate it 90 degrees anti-clockwise.
The problem here is likely the way you're reading the dataset arrays. If you transpose the array being read (e.g., for a numpy array, your_array.T), your EMNIST characters should be in the correct orientation.
snippet to transform eminst in pytorch (just to see transforms necessary)
dataset = torchvision.datasets.EMNIST(
path_data,
download=True,
split='balanced',
train=not is_test_data,
transform=torchvision.transforms.Compose([
lambda img: torchvision.transforms.functional.rotate(img, -90),
lambda img: torchvision.transforms.functional.hflip(img),
torchvision.transforms.ToTensor()
])
)
As Ankit Tiwari has told .
After flipping horizontally and rotating , it looks ok .
Thanks.
See
This works in Ubuntu 16.04 / Anaconda 3.6, despite Python 2 just comment out Print ... quick way to validate EMNIST balanced and MNIST loading

Unexpected output when finding variance of an image in OpenCV -Python

My program finds the varaince values of an image at each window of a gridded image. The problem is when I print the values they don't match with what is shown in the ouput image. I have included an example image below.
Here is my code:
#import packages
import numpy as np
import cv2
import dateutil
import llist
from matplotlib import pyplot as plt
import argparse
#Read in image as grey-scale
img = cv2.imread('images/0021.jpg', 0)
#Set scale of grid
scale = 6
#Get x and y components of image
y_len,x_len = img.shape
variance = []
for y in range(scale):
for x in range(scale):
#Crop image 9*9 windows
cropped_img=img[(y*y_len)/scale:((y+1)*y_len)/scale,(x*x_len)/scale:((x+1)*x_len)/scale]
(mean,stdv) = cv2.meanStdDev(cropped_img)
var = stdv*stdv
cropped_img[:] = var
#Print mean_values array
variance.append([var])
variance=np.asarray(variance)
np.set_printoptions(suppress=True, precision=3)
print variance.reshape(1,scale,scale)
cv2.imshow('output_var',img)
#cv2.imwrite('images/output_var_300.jpg',img,[int(cv2.IMWRITE_JPEG_QUALITY), 90])
cv2.waitKey(0)
cv2.destroyAllWindows()
Here is the output image of the code above:
From what I can tell the values below don't match the image above. Does anybody have any idea what is happening here?
print variance.reshape(1,scale,scale)
#[[[ 17.208 43.201 215.305 1101.816 1591.606 2453.611]
# [ 46.664 121.162 326.59 809.223 1021.599 5330.989]
# [ 47.754 64.69 705.875 1625.177 3564.494 10148.449]
# [ 19.153 201.864 289.258 632.737 5285.449 4257.597]
# [ 37.621 159.51 271.725 282.291 2239.097 759.007]
# [ 26.108 98.456 32.958 505.609 575.916 70.741]]]
Thank you in advance.
EDIT : Here is a more realistic output image for those who are interested:
Let's take for example, the second row of variance. Since the color values are in range 0-255 per channel, we can try wrapping your values to fit into that range:
>>> row = [46.664, 121.162, 326.59, 809.223, 1021.599, 5330.989]
>>> wrapped = [x % 256 for x in row]
>>> wrapped
[46.66, 121.16, 70.58, 41.22, 253.59, 210.98]
And voila, it makes sense now.

Python: raw image data to grayscale

I have raw image data stored in a text file, in a format like this and I would like to make it a 2D array and convert it to grayscale.
0
0
0
0
24
243
227
223
224
225
227
228
228
What I would like to do is take this data, convert it to grayscale, and display the image. My plan is to use numpy...I have this working in matlab, but I'm having difficulty implementing it in python
I have tried to do the following:
import numpy as np
from PIL import Image
from pylab import *
ROWS = 144
COLUMNS = 175
raw_image = []
lines = [line.strip().split(',') for line in open('CAMERA.txt')
for i in lines:
raw_image.append(i)
mat_image = np.zeros((ROWS, COLUMNS), dtype = int)
for i in rage(ROWS):
for j in range(COLUMNS):
mat_image.itemset(i, j, raw_image[(i-1)*COLUMNS + j])
plt.gray()
axes = app.image.add_subplot(111)
self.im = Image.fromarray(mat_image)
axes.imshow(self.im)
app.imageCanvas.draw()
I've also tried doing:
np.reshape(raw_image, ROWS, COLUMNS)
However neither of these approaches work. Does anyone have any suggestions?
Thanks in advance.
The program below could do what you want if I correctly interpreted what you want to do ;-)
import numpy as np
import matplotlib.pyplot as plt
if __name__=='__main__':
rows = 144
columns = 175
camera_image = np.loadtxt(r'path/to/filename')
if(not camera_image.size == rows * columns):
raise Exception('Size mismatch!')
my_image = np.reshape(camera_image, (rows, columns)) / 255.0
figure = plt.figure()
axes = figure.add_subplot(1, 1, 1)
axes.imshow(my_image)
plt.show()
Kind regards
Here's a pretty simple method of going from text integers to PIL image that works for me:
import numpy as np
from PIL import Image
ROWS = 50
COLUMNS = 50
# greyValues.txt is 2500 RGB values 0-255 one per line
arr = np.genfromtxt('greyValues.txt', dtype=np.int8)
arr.shape = (ROWS, COLUMNS)
img = Image.fromarray(arr, 'L')
img.show()
img.save("textimage.jpg")

Categories