Trying to create a ghost 3d image with a known volume to create a calibrated gold standard : a sphere.
I've tried this code but it doesn't provide me what i'm really want.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import medpy.io as mdpy
from scipy import signal
def create_bin_sphere(arr_size, center, r):
coords = np.ogrid[:arr_size[0], :arr_size[1], :arr_size[2]]
distance = np.sqrt((coords[0] - center[0])**2 + (coords[1]-center[1])**2 + (coords[2]-center[2])**2)
return 10*(distance <= r)
arr_size = (100,100,100)
sphere_center = (50,50,50)
r=30
sphere = create_bin_sphere(arr_size,sphere_center, r)
kernel = np.array([[[0,1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1,0]]])
sphere_smooth = scipy.signal.oaconvolve(sphere, kernel, mode="same")
from medpy.io import load, save
save(sphere_smooth ,r'x\x\x\x\x\sphere_smooth.mhd')
Does not work as i wish :image in itk snap in x plan
I would rather not change the sphere shape (the "smoothed" become ovoid), have the blurr effect on the whole circumference and reducing its thickness, and finally invert the density (white outside and grey inside the sphere).
If you can help me i will appreciate...
Related
I cannot figure out how to draw a pixel in ipycanvas. I am drawing rectangles instead of pixels and this makes drawing very slow.
Drawing a rectangle using:
canvas.fill_rect
Code to display image in ipycanvas :
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import ipycanvas
from ipycanvas import Canvas
import requests
from io import BytesIO
url = r"https://wallpapercave.com/dwp1x/wp1816238.jpg"
response = requests.get(url)
img = Image.open(BytesIO(response.content))
array = img.tobytes()
canvas = Canvas(width=img.width, height=img.height)
with ipycanvas.hold_canvas():
for i in range(int(len(array)/3)):
r = array[i * 3 + 0] # red
g = array[i * 3 + 1] # green
b = array[i * 3 + 2] # blue
canvas.fill_style = f"#{r:02x}{g:02x}{b:02x}" # setting color
canvas.fill_rect(i%img.width, int(i/img.width), 1, 1) # drawing rectangle
canvas
Output:
I am drawing image pixel by pixel because I want to apply filters in images.
How to draw pixels in ipycanvas?
Not sure if this will help but given you're talking about filtering I'd assume you mean things like convolutions. Numpy and Scipy help a lot and provide various ways of applying these and work well with images from Pillow.
For example:
import requests
from io import BytesIO
from PIL import Image
import numpy as np
from scipy import signal
image_req = requests.get("https://wallpapercave.com/dwp1x/wp1816238.jpg")
image_req.raise_for_status()
image = Image.open(BytesIO(image_req.content))
# create gaussian glur of a given standard deviation
sd = 3
filt = np.outer(*2*[signal.windows.gaussian(int(sd*5)|1, sd)])
filt /= filt.sum()
# interpret image as 3d array
arr = np.array(image)
# apply it to each channel independently, this loop runs in ~0.1 seconds
for chan in range(3):
arr[:,:,chan] = signal.oaconvolve(arr[:,:,chan], filt, mode='same')
# array back into image for display in notebook
Image.fromarray(arr)
This produces an image like:
I have matrix filled with zeros and a rectangle filled by ones on a region of this matrix, like this
and I want to rotate the rectangle to an arbitrary angle (30° in this case) like this
import numpy as np
import matplotlib.pyplot as plt
n_x = 200
n_y = 200
data = np.zeros((n_x, n_y))
data[20:50, 20:40] = 1
plt.imshow(data)
plt.show()
How about using scipy?
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import rotate
n_x = 200
n_y = 200
data = np.zeros((n_x, n_y))
data[20:50, 20:40] = 1
angle = 30
data = rotate(data, angle)
plt.imshow(data)
plt.show()
Of course this is around the middle of the image. If you want to rotate around the center of the rectangle, I would suggest translating it to the middle of the image, rotate it and then translate it back.
From a mathematical point of view you could solve the problem by transforming
the cartesian coordinates of the ones into polar coordinates relative to the center of the rectangle.
r = sqrt(x²+y²)
phi = atan2(y,x)
(Note that x and y have to be relative to the center of rotation)
With polar coordinates it is no problem to rotate, since you just have to add the desired angle to phi and than transform back into cartesian coordinates.
x = r*cos(phi)
y = r*sin(phi)
(And again, the resulting coordinates would be with respect to the center of rotation, so you need to add them to the cartesian vector which points to the center)
I have a numpy array for an image that I read in from a FITS file. I rotated it by N degrees using scipy.ndimage.interpolation.rotate. Then I want to figure out where some point (x,y) in the original non-rotated frame ends up in the rotated image -- i.e., what are the rotated frame coordinates (x',y')?
This should be a very simple rotation matrix problem but if I do the usual mathematical or programming based rotation equations, the new (x',y') do not end up where they originally were. I suspect this has something to do with needing a translation matrix as well because the scipy rotate function is based on the origin (0,0) rather than the actual center of the image array.
Can someone please tell me how to get the rotated frame (x',y')? As an example, you could use
from scipy import misc
from scipy.ndimage import rotate
data_orig = misc.face()
data_rot = rotate(data_orig,66) # data array
x0,y0 = 580,300 # left eye; (xrot,yrot) should point there
P.S. The following two related questions' answers do not help me:
Find new coordinates of a point after rotation
New coordinates after image rotation using scipy.ndimage.rotate
As usual with rotations, one needs to translate to the origin, then rotate, then translate back. Here, we can take the center of the image as origin.
import numpy as np
import matplotlib.pyplot as plt
from scipy import misc
from scipy.ndimage import rotate
data_orig = misc.face()
x0,y0 = 580,300 # left eye; (xrot,yrot) should point there
def rot(image, xy, angle):
im_rot = rotate(image,angle)
org_center = (np.array(image.shape[:2][::-1])-1)/2.
rot_center = (np.array(im_rot.shape[:2][::-1])-1)/2.
org = xy-org_center
a = np.deg2rad(angle)
new = np.array([org[0]*np.cos(a) + org[1]*np.sin(a),
-org[0]*np.sin(a) + org[1]*np.cos(a) ])
return im_rot, new+rot_center
fig,axes = plt.subplots(2,2)
axes[0,0].imshow(data_orig)
axes[0,0].scatter(x0,y0,c="r" )
axes[0,0].set_title("original")
for i, angle in enumerate([66,-32,90]):
data_rot, (x1,y1) = rot(data_orig, np.array([x0,y0]), angle)
axes.flatten()[i+1].imshow(data_rot)
axes.flatten()[i+1].scatter(x1,y1,c="r" )
axes.flatten()[i+1].set_title("Rotation: {}deg".format(angle))
plt.show()
I am trying to implement adaptive histogram equalization in python. I take an image and split it into smaller regions and then apply the traditional histogram equalization to it. I then combine the smaller images into one and obtain a final resultant image. The final image appears to be very blocky in nature and has different contrast levels for each individual region. Is there a way I could maintain a uniform contrast for each individual image so that it looks like a single image instead of smaller images stitched together.
import cv2
import numpy as np
from matplotlib import pyplot as plt
from scipy.misc import imsave
from scipy import ndimage
from scipy import misc
import scipy.misc
import scipy
import image_slicer
from image_slicer import join
from PIL import Image
img = 'watch.png'
num_tiles = 25
tiles = image_slicer.slice(img, num_tiles)
for tile in tiles:
img = scipy.misc.imread(tile.filename)
hist,bins = np.histogram(img.flatten(),256,[0,256])
cdf = hist.cumsum()
cdf_normalized = cdf *hist.max()/ cdf.max()
plt.plot(cdf_normalized, color = 'g')
plt.hist(img.flatten(),256,[0,256], color = 'g')
plt.xlim([0,256])
plt.legend(('cdf','histogram'), loc = 'upper left')
cdf_m = np.ma.masked_equal(cdf,0)
cdf_o = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
cdf = np.ma.filled(cdf_o,0).astype('uint8')
img3 = cdf[img]
cv2.imwrite(tile.filename,img3)
tile.image = Image.open(tile.filename
image = join(tiles)
image.save('watch-join.png')
I reviewed the actual algorithm and came up with the following implementation. I am sure there is a better way to do this. Any suggestions are appreciated.
import numpy as np
import cv2
img = cv2.imread('watch.png',0)
print img
img_size=img.shape
print img_size
img_mod = np.zeros((600, 800))
for i in range(0,img_size[0]-30):
for j in range(0,img_size[1]-30):
kernel = img[i:i+30,j:j+30]
for k in range(0,30):
for l in range(0,30):
element = kernel[k,l]
rank = 0
for m in range(0,30):
for n in range(0,30):
if(kernel[k,l]>kernel[m,n]):
rank = rank + 1
img_mod[i,j] = ((rank * 255 )/900)
im = np.array(img_mod, dtype = np.uint8)
cv2.imwrite('target.png',im)
I want to use OCR to capture the bowling scores from the monitor at the lances. I had a look at this sudoku solver, as I think its pretty similar - numbers and grids right? It has trouble finding the horizontal lines. Has anyone got any tips for pre-processing this image to make it easier to detect the lines (or numbers!). Also any tips for how to deal with the split (the orange ellipse around some of the 8's int he image)?
So far I have got the outline of the score area and cropped it.
import matplotlib
matplotlib.use('TkAgg')
from skimage import io
import numpy as np
import matplotlib.pyplot as plt
from skimage import measure
from skimage.color import rgb2gray
# import pytesseract
from matplotlib.path import Path
from qhd import *
def polygonArea(poly):
"""
Return area of an unclosed polygon.
:see: https://stackoverflow.com/a/451482
:param poly: (n,2)-array
"""
# we need a plain list for the following operations
if isinstance(poly, np.ndarray):
poly = poly.tolist()
segments = zip(poly, poly[1:] + [poly[0]])
return 0.5 * abs(sum(x0*y1 - x1*y0
for ((x0, y0), (x1, y1)) in segments))
filename = 'good.jpg'
image = io.imread(filename)
image = rgb2gray(image)
# Find contours at a constant value of 0.8
contours = measure.find_contours(image, 0.4)
# Display the image and plot all contours found
fig, ax = plt.subplots()
c = 0
biggest = None
biggest_size = 0
for n, contour in enumerate(contours):
curr_size = polygonArea(contour)
if curr_size > biggest_size:
biggest = contour
biggest_size = curr_size
biggest = qhull2D(biggest)
# Approximate that so we just get a rectangle.
biggest = measure.approximate_polygon(biggest, 500)
# vertices of the cropping polygon
yc = biggest[:,0]
xc = biggest[:,1]
xycrop = np.vstack((xc, yc)).T
# xy coordinates for each pixel in the image
nr, nc = image.shape
ygrid, xgrid = np.mgrid[:nr, :nc]
xypix = np.vstack((xgrid.ravel(), ygrid.ravel())).T
# construct a Path from the vertices
pth = Path(xycrop, closed=False)
# test which pixels fall within the path
mask = pth.contains_points(xypix)
# reshape to the same size as the image
mask = mask.reshape(image.shape)
# create a masked array
masked = np.ma.masked_array(image, ~mask)
# if you want to get rid of the blank space above and below the cropped
# region, use the min and max x, y values of the cropping polygon:
xmin, xmax = int(xc.min()), int(np.ceil(xc.max()))
ymin, ymax = int(yc.min()), int(np.ceil(yc.max()))
trimmed = masked[ymin:ymax, xmin:xmax]
plt.imshow(trimmed, cmap=plt.cm.gray), plt.title('trimmed')
plt.show()
https://imgur.com/LijB85I is an example of how the score is displayed.