I have created a numpy array shape(11 x 11) with all pixels 0 excluding one column filled with 1.
[[ 0 0 0 0 0 1 0 0 0 0 0 ]
[ 0 0 0 0 0 1 0 0 0 0 0 ]
[ 0 0 0 0 0 1 0 0 0 0 0 ]
[ 0 0 0 0 0 1 0 0 0 0 0 ]
[ 0 0 0 0 0 1 0 0 0 0 0 ]
[ 0 0 0 0 0 1 0 0 0 0 0 ]
[ 0 0 0 0 0 1 0 0 0 0 0 ]
[ 0 0 0 0 0 1 0 0 0 0 0 ]
[ 0 0 0 0 0 1 0 0 0 0 0 ]
[ 0 0 0 0 0 1 0 0 0 0 0 ]
[ 0 0 0 0 0 1 0 0 0 0 0 ]]
The array was saved as a png image using matplotlib.imsave yielding the expected image - black background with a white line in the middle.
When trying to reimport the saved png image
skipy.imread and Pil.Image.Open yield an array of the form
[[[ 68 1 84 255]
[ 68 1 84 255]
[ 68 1 84 255]
[ 68 1 84 255]
[ 68 1 84 255]
[253 231 36 255]
[ 68 1 84 255]
[ 68 1 84 255]
[ 68 1 84 255]
[ 68 1 84 255]
[ 68 1 84 255]]
...
]
What does this file format mean (could not find an explanation in the scikit image documentation) ?
And how do I convert it back to the binary input image?
What you see is explained thusly:
your data was grayscale
then you plotted that with a colormap
-- the line looks yellow and the background looks dark blue/violet?
then you told matplotlib to save that false-color picture
then you read that false-color picture back
now you have RGBA pixel data. you see the first pixel row, and each value of each color pixel
If you wanted to maintain the grayscale appearance of your data, you'd have some choices.
Use plt.imshow(arr, cmap="gray"), which uses a gray color map rather than a colorful one.
When reading the image, and also converting any color to grayscale, you can choose scikit-image or OpenCV. OpenCV has cv.imread(fname, cv.IMREAD_GRAYSCALE). scikit-image offers skimage.io.imread(fname, as_gray=True).
And really you should use scikit-image or OpenCV for writing your picture in the first place. Matplotlib is for plotting, not for storing data authentically. Matplotlib took your data and rescaled it so the maximum and minimum value become 0 and 1, which is black and white for the gray cmap.
On grayscale, a pixel with value 1 doesn't appear white - this simply happens because matplotlib normalizes the image before displaying it.
Choose either:
a) Keep the original binary values, then the saved image won't have a white line in the middle
b) Have a white line in the middle, but then you'll have to modify the array before saving and after loading it.
Ad b)
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# This is the array you have
arr = np.zeros((11, 11), dtype=np.uint8)
arr[:, 5] = 1
plt.figure()
plt.imshow(arr, cmap='gray')
plt.show()
# This will ensure that the line appears white in the .png
arr_png = arr * 255 # 2**8 - 1
# Write to disk
cv.imwrite('line.png', arr_png)
# Load from disk
arr_from_disk = np.array(cv.imread('line.png', 0), dtype=np.uint8)
# Rescale
arr_from_disk = np.divide(arr_from_disk, 255)
assert np.array_equal(arr, arr_from_disk), 'Oops'
I want to find the vertices given the following:
`A = np.array([
[-1,2/3,0,0,0,0,0,0,0],
[1,-2/3,0,0,0,0,0,0,0],
[-1,0,0,2/3,0,0,0,0,0],
[-1,0,2/3,0,0,0,0,0,0],
[1,0,-2/3,0,0,0,0,0,0],
[-1,0,0,0,2/3,0,0,0,0],
[-1,0,0,0,2/3,0,0,0,0],
[1,0,0,-2/3,0,0,0,0,0],
[-1,2/3,0,0,0,0,0,0,0]])`
`b = np.array([-1/3, 1/3, -2/3, 1/3, -1/3, 0, -2/3, 2/3, -1/3])` .
I tried to compute the vertices by using the
vertices = pypoman.compute_polytope_vertices(A,b).
However, I get the following error:
raise Exception("Polyhedron is not a polytope")
Exception: Polyhedron is not a polytope".
Did anyone have a problem like this?
Use pycddlib:
# -*- coding: utf-8 -*-
import numpy as np
import cdd as pcdd
import fractions as frac
A = np.array([
[-1,frac.Fraction(2,3),0,0,0,0,0,0,0],
[1,-frac.Fraction(2,3),0,0,0,0,0,0,0],
[-1,0,0,frac.Fraction(2,3),0,0,0,0,0],
[-1,0,frac.Fraction(2,3),0,0,0,0,0,0],
[1,0,-frac.Fraction(2,3),0,0,0,0,0,0],
[-1,0,0,0,frac.Fraction(2,3),0,0,0,0],
[-1,0,0,0,frac.Fraction(2,3),0,0,0,0],
[1,0,0,-frac.Fraction(2,3),0,0,0,0,0],
[-1,frac.Fraction(2,3),0,0,0,0,0,0,0]])
b = np.array([
[-frac.Fraction(1,3)],
[frac.Fraction(1,3)],
[-frac.Fraction(2,3)],
[frac.Fraction(1,3)],
[-frac.Fraction(1,3)],
[0],
[-frac.Fraction(2,3)],
[frac.Fraction(2,3)],
[-frac.Fraction(1,3)]
])
M = np.hstack( (b, -A) )
mat = pcdd.Matrix(M, linear=False, number_type="fraction")
mat.rep_type = pcdd.RepType.INEQUALITY
poly = pcdd.Polyhedron(mat)
ext = poly.get_generators()
print(ext)
Giving:
1 2/3 1/2 3/2 0 0 0 0 0 0
0 1 3/2 3/2 3/2 0 0 0 0 0
0 2/3 1 1 1 1 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 1
Indeed, this is not a polytope. A "1" in the first column means it is an extreme point, and here there is only one.
I am trying to create a structure to use in a C library provided (DLL),
How the following structure (given in the documentation) can be defined?
#define A 10
#define B 20
typedef struct
{
int32_t size;
int32_t num;
char buf1[A][B];
char buf2[A][B];
char buf3[A][B];
} INSTRUCT;
My attempt to define it in python using ctypes was like so:
from ctypes import*
char_buff1 = ((c_char * 10) * 20)
char_buff2 = ((c_char * 10) * 20)
char_buff3 = ((c_char * 10) * 20)
class INSTRUCT(Structure):
_fields_=[("size",c_int32),("num",c_int32),("buf1",char_buff1),("buf2",char_buff2),("buf3",char_buff3)]
Can int32_t be replaced with c_int_32 in ctypes?
Is it correct way to define the structure?
Then I tried to feed the pointer of the structure to the DLL function and check what it returns as follows:
dlllib = CDLL("some.dll")
somefunction = dlllib.some_function
somefunction.argtypes = [POINTER(INSTRUCT)]
INSTRUCT().size
INSTRUCT().num
print(np.ctypeslib.as_array(INSTRUCT().buf1))
However, I can only the return is 0 and unmodified by the function -- equal to the one defined before the C function call.
I am not sure at which stage the problem occurs, however, there are no errors, the code executes normally.
Unfortunately, I don't have the C code available, only the input parameters for the function.
Best regards
The array definition is wrong. In ctypes, the array indices need to be reversed to index the array the way C does. For example, the equivalent of char buf[x][y] in Python with ctypes is buf = (c_char * y * x)(). Note that the bounds are reversed. Otherwise, your definition was correct.
Note that using c_char will return text characters for array values. If you want integers, use c_int8. I'll use the latter below.
Example:
from ctypes import *
import numpy as np
A,B = 10,20
ARRAY = c_int8 * B * A # build as B,A
class INSTRUCT(Structure):
_fields_=[("size",c_int32),
("num",c_int32),
("buf1",ARRAY),
("buf2",ARRAY),
("buf3",ARRAY)]
i = INSTRUCT()
i.buf1[9][19] = 1 # access indices as A,B
print(np.ctypeslib.as_array(i.buf1))
[[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 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 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 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 1]] # 1 in correct location
Your example of accessing used INSTRUCT() which creates a new, zeroed object each time. Create a single instance and pass it to a function like so:
dlllib = CDLL("some.dll")
somefunction = dlllib.some_function
somefunction.argtypes = [POINTER(INSTRUCT)]
i = INSTRUCT() # make an instance
somefunction(byref(i)) # byref() passes address of a ctypes object.
I have a binary array of size 64x64x64, where a volume of 40x40x40 is set to "1" and rest is "0". I have been trying to rotate this cube about its center around z-axis using skimage.transform.rotate and also Opencv as:
def rotateImage(image, angle):
row, col = image.shape
center = tuple(np.array([row, col]) / 2)
rot_mat = cv2.getRotationMatrix2D(center, angle, 1.0)
new_image = cv2.warpAffine(image, rot_mat, (col, row))
return new_image
In the case of openCV, I tried, 2D rotation of each idividual slices in a cube (Cube[:,:,n=1,2,3...p]).
After rotating, total sum of the values in the array changes. This may be caused by interpolation during rotation. How can I rotate 3D array of this kind without adding anything to the array?
Ok so I understand now what you are asking. The closest I can come up with is scipy.ndimage. But there is a way interface with imagej from python if which might be easier. But here is what I did with scipy.ndimage:
from scipy.ndimage import interpolation
angle = 25 #angle should be in degrees
Rotatedim = interpolation.rotate(yourimage, angle, reshape = False,output = np.int32, order = 5,prefilter = False)
This worked for some angles to preserve the some and not others, perhaps by playing around more with the parameters you might be able to get your desired outcome.
One option is to convert into sparse, and transform the coordinates using a matrix rotation. Then transform back into dense. In 2 dimensions, this looks like:
import numpy as np
import scipy.sparse
import math
N = 10
space = np.zeros((N, N), dtype=np.int8)
space[3:7, 3:7].fill(1)
print(space)
print(np.sum(space))
space_coo = scipy.sparse.coo_matrix(space)
Coords = np.array(space_coo.nonzero()) - 3
theta = 30 * 3.1416 / 180
R = np.array([[math.cos(theta), math.sin(theta)], [-math.sin(theta), math.cos(theta)]])
space2_coords = R.dot(Coords)
space2_coords = np.round(space2_coords)
space2_coords += 3
space2_sparse = scipy.sparse.coo_matrix(([1] * space2_coords.shape[1], (space2_coords[0], space2_coords[1])), shape=(N, N))
space2 = space2_sparse.todense()
print(space2)
print(np.sum(space2))
Output:
[[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 1 1 1 1 0 0 0]
[0 0 0 1 1 1 1 0 0 0]
[0 0 0 1 1 1 1 0 0 0]
[0 0 0 1 1 1 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 0 0 0 0 0 0 0]]
16
[[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 1 0 0 0 0 0 0]
[0 0 1 1 1 1 0 0 0 0]
[0 0 1 1 1 1 1 0 0 0]
[0 1 1 0 1 1 0 0 0 0]
[0 0 0 1 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]]
16
The advantage is that you'll get exactly as many 1 values before and after the transform. The downsides is that you might get 'holes', as above, and/or duplicate coordinates, giving values of '2' in the final dense matrix.