def my_gradient(imin, se, grey=False): """ Returns morphological gradient for grey level images, or the LAB gradient for color images. Input: imin : grey level or color image se : structuring element grey (Bool): if set to True, on colour images we compute the morphological gradient on the green channel. Output: imout : UINT8 image containing the gradient """ if imin.getTypeAsString() == "RGB": if grey is True: tmpIm = sp.Image() imout = sp.Image(tmpIm) sp.copyChannel(imin, 1, tmpIm) sp.gradient(tmpIm, imout, se) else: imout = sp.Image(imin) gradient_LAB(imin, imout, se) else: imout = sp.Image(imin) sp.gradient(imin, imout, se) return imout
def im_labelled_square_grid_points(size, step, margin=1): """ Creates a regular grid of square cells. Input: size : list of 2d dimensions of output image step: minimum distance between two cell centers (we suppose that the step is the same in all directions) Output: imout : UINT16 image containing the labelled grid centers. imout2 : UINT16 image containing the labelled cells. """ imout = sp.Image(size[0], size[1]) imout2 = sp.Image(imout,"UINT16") imout = sp.Image(imout2) np_im = imout.getNumArray() np_im.fill(0) cells_im = imout2.getNumArray() cells_im.fill(0) label = 1 for x in range(size[0]/step+1): for y in range(size[1]/step+1): center_x = np.min([ x*step + step/2, size[0]-1]) center_y = np.min([ y*step + step/2, size[1]-1]) np_im[center_x, center_y] = label cells_im[x*step+margin:(x+1)*step-margin, y*step+margin:(y+1)*step-margin] = label label += 1 return (imout, imout2)
def main(args): image = cv2.imread(args.image_path, cv2.IMREAD_GRAYSCALE) image = (image.astype(np.float) - image.min()) * 255 / (image.max() - image.min()) image = image.astype(np.uint8) original = sp.Image() original.fromNumArray(image.transpose()) closed = sp.Image() for size in args.path_sizes: sp.ImPathClosing(original, size, closed) sp.write(closed, "matlab_closing_%s.png" % size)
def one_min_per_grid_cell(im_cells_lbl, blobs, im_labelled_minima, se): """ Enables to select the best marker of each cell of the grid. Input: im_cells_lbl (UINT16): image of labelled cells. blobs: definition of each connected component im_labelled_minima (UINT16): image of markers candidates labelled with their ranking for some given criterium (e.g. surfacic extinction), i.e. "1" is the best. se: structuring element. """ ## Selection of the marker with the best ranking in each cell: imtmp = sp.Image(im_cells_lbl) sp.test(im_labelled_minima, im_labelled_minima, 65335, im_labelled_minima) minVals = sp.measMinVals(im_labelled_minima, blobs) sp.applyLookup(im_cells_lbl, minVals, imtmp) sp.compare(im_labelled_minima, "==", imtmp, im_labelled_minima, 0, im_labelled_minima) ## Selection of only one marker if several met the previous requirement in the same cell: sp.label(im_labelled_minima, imtmp, se) blobs2 = sp.computeBlobs(im_labelled_minima) maxVals = sp.measMaxVals(imtmp, blobs) sp.applyLookup(im_cells_lbl, maxVals, im_labelled_minima) sp.compare(imtmp, "==", im_labelled_minima, imtmp, 0, imtmp) sp.test(im_cells_lbl, imtmp, 0, im_labelled_minima) return
def gray_area_filtering(imin, size): """ Gray level area filtering. Only V4 connexity is available. """ imtmp = sp.Image(imin) sp.areaClose(imin, size, imtmp) sp.areaOpen(imtmp, size, imin)
def my_area_filtering(imin, size): """ Filtering of a gray level or color image. Only V4 connexity is available. """ if imin.getTypeAsString() == "RGB": im = sp.Image() sp.splitChannels(imin, im) for i in range(3): gray_area_filtering(im.getSlice(i), size) sp.mergeChannels(im, imin) else: gray_area_filtering(imin, size)
def X_singlePlot(imIn, ax, label): if (imIn.getTypeAsString() == "RGB"): im3ch = sp.Image() sp.splitChannels(imIn, im3ch) imArr = im3ch.getNumArray() imArr = np.rot90(imArr, -1) imArr = np.fliplr(imArr) ax.imshow(imArr) else: imInArr = imIn.getNumArray() imInArr = np.rot90(imInArr, -1) imInArr = np.fliplr(imInArr) if not label: ax.imshow(imInArr, cmap=cm.Greys_r, norm=cl.NoNorm()) else: ax.imshow(imInArr, cmap=randcmap)
def smilToNumpyPlotNoNorm(imIn, labelImage=False): if (imIn.getTypeAsString() == "RGB"): imIn3ch = sp.Image() sp.splitChannels(imIn, imIn3ch) imInArr = imIn3ch.getNumArray() imInArr = np.rot90(imInArr, -1) imInArr = np.fliplr(imInArr) plt.figure() plt.imshow(imInArr) plt.show() else: imInArr = imIn.getNumArray() imInArr = np.rot90(imInArr, -1) imInArr = np.fliplr(imInArr) if not labelImage: plt.figure() plt.imshow(imInArr, cmap="gray", norm=cl.NoNorm()) plt.show() else: plt.figure() plt.imshow(imInArr, cmap=randcmap) plt.show()
import smilPython as sp im = sp.Image("cells.png") imDist = sp.Image(im) imMask = sp.Image(im) imMark = sp.Image(im) imGeoDist = sp.Image(im) # create a marker image, the same as the original image except at # some point inside the "true" region, which is set to "0" nl = sp.HexSE() sp.distance(im, imDist, nl) sp.compare(imDist, "==", sp.maxVal(imDist), 0, im, imMark) # use the original image as the mask. sp.copy(im, imMask) sp.distanceGeodesic(imMark, imMask, imGeoDist, nl) imGeoDist.show() sp.maxVal(imGeoDist)
import smilPython as sm import numpy as np # read a PNG image file (8 bits gray image) file = "my-image.png") img = sm.Image(file) # show the image img.show(file) # get a NumPy array p = img.getNumArray() # let's threshold the image t = 127 p[p >= t] = 255 p[p < t] = 0 # Call the "modified" method in order to update the viewer content img.modified()
import smilPython as sp im = sp.Image("lena.png") # set new default StrElt and save old one saveSE = sp.Morpho.getDefaultSE() sp.Morpho.setDefaultSE(sp.SquSE)) # do something imd = sp.Image(im) sp.dilate(im, imd, 3) # restore old default StrElt sp.Morpho.setDefaultSE(saveSE)
in_file = "init.png" Size = 20 tolerance = 2 step = 10 NN = 100 img = Image.open(in_file) XX, YY = img.size img_out = np.zeros((YY, XX), np.uint8) for yy in np.arange(0, YY, NN): for xx in np.arange(0, XX, NN): img_ii = np.array(img)[yy:min(yy + NN, YY), xx:min(xx + NN, XX)].transpose() im_in = smil.Image(*img_ii.shape) im_in_np = im_in.getNumArray() im_in_np[:] = img_ii[:] im_out = smil.Image(im_in) smil.parsimoniousPathOpening(im_in, Size, tolerance, step, False, im_out) im_out_np = im_out.getNumArray().transpose() img_out_slice = img_out[yy:min(yy + NN, YY), xx:min(xx + NN, XX)] img_out_slice[:] = im_out_np[:] img_reconstr = ImageFromArray(img_out) img_out = ImageFromArray(img_out) im_in = ImageFromArray(np.array(img)) smil.geoBuild(img_out, im_in, img_reconstr)
import smilPython as sp import numpy as np from numpy import linalg as la # get image imIn = sp.Image("https://smil.cmm.minesparis.psl.eu/images/tools.png") # labelize input image imThr = sp.Image(imIn) sp.topHat(imIn, imThr, sp.hSE(20)) sp.threshold(imThr, imThr) imLbl = sp.Image(imIn, "UINT16") sp.label(imThr, imLbl) # compute blobs and get their data blobs = sp.computeBlobs(imLbl) central = True inertia = sp.blobsInertiaMatrix(imIn, blobs, central) barys = sp.blobsBarycenter(imIn, blobs) nshape = (2, 2) if imIn.getDimension() == 3: nshape = (3, 3) for k in inertia.keys(): print("=" * 64) s = "" for v in barys[k]: s += " {:6.1f}".format(v) print("Blob label : {:3d} - Barycenter :{:}".format(k, s)) # Smil returns inertia matrix as a vector. Reshape it.
import smilPython as sp imIn = sp.Image("https://smil.cmm.minesparis.psl.eu/images/lena.png") imOut = sp.Image(imIn) imIn.show() imOut.show() sp.gaussianFilter(imIn, 3, imOut)
import smilPython as sp im = sp.Image("https://smil.cmm.minesparis.psl.eu/images/balls.png") imLbl1 = sp.Image(im, "UINT16") imLbl2 = sp.Image(imLbl1) sp.label(im, imLbl1) # We can use a Smil Map # lookup = Map_UINT16_UINT16() # or directly a python dict lookup = dict() lookup[1] = 2 lookup[5] = 3 lookup[2] = 1 sp.applyLookup(imLbl1, lookup, imLbl2) imLbl1.showLabel() imLbl2.showLabel()
for h in hdr: s += h.rjust(16) print(s) for label in m.keys(): s = '{:3} :'.format(label) for v in m[label]: s += ' {:14.2f}'.format(v) print(s) # Serious work begins here # binaryImage = False if binaryImage: imageName = "https://smil.cmm.minesparis.psl.eu/images/balls.png" imo = sp.Image(imageName) iml = sp.Image(imo, 'UINT16') # normalize binary image values imo /= 255 sp.label(imo, iml) else: imageName = "https://smil.cmm.minesparis.psl.eu/images/tools.png" imo = sp.Image(imageName) imThr = sp.Image(imo) sp.topHat(imo, imThr, sp.hSE(20)) sp.threshold(imThr, imThr) iml = sp.Image(imo, "UINT16") sp.label(imThr, iml) # create blobs blobs = sp.computeBlobs(iml)
import smilPython as sm import numpy as np # create a 10x10 NumPy array a = np.array(range(100), 'uint8') a = a.reshape(10, 10) # creates a Smil image and set it's content to "a" img = sm.Image() img.fromNumArray(a)
import smilPython as sp im = sp.Image("balls.png") iml = sp.Image(im) # this is just a binary image - no need to segment sp.label(im, iml) iml.showLabel() # create blobs structure blobs = sp.computeBlobs(iml) # evaluate some measures : areas = sp.blobsArea(blobs) barys = sp.blobsBarycenter(im, blobs) # print areas and barycenters of each region print("{:3s} - {:>6s} - {:>13s}".format("ID", "Area", "Barycenter")) for k in blobs.keys(): bary = barys[k] print("{:3d} - {:6.0f} - {:6.0f} {:6.0f}".format(k, areas[k], bary[0], bary[1]))
import smilPython as sp imIn = sp.Image(10, 10, 10) imOut = sp.Image(im) imTmp = sp.Image(im) # rotation 90 degres around Y axis # 1. exchange axes y and z sp.matTranspose(imIn, "xzy", imTmp) # 2. rotate image around new z axis sp.rotateX90(imTmp, 1, imTmp) # 3. put axis y back sp.matTranspose(imTmp, "xzy", imOut)
import smilPython as sp fname = "imageraw.raw" type = 'UINT16' width = 256 height = 384 depth = 512 img = sp.Image(type) sp.readRAW(fname, width, height, depth, img)
import smilPython as sp img = sp.Image() r = sp.getFileInfo("lena.jpg", img) # Note, this is the same as : img = sp.Image("lena.jpg")
import smilPython as sp import numpy as np # Create an image sx = 256 sy = 384 im1 = sp.Image(sx, sy) im1.show() # Create a numpy array containing the real image pixels imArr = im1.getNumArray() # Display the dimensions of the created array print("Array dims:", imArr.shape) # Do something with the array... E.g., draw a circle imArr[:] = 0 # the circle will be centered at the center of the image radius, cx, cy = 64, sy // 2, sx // 2 y, x = np.ogrid[0:sx, 0:sy] # get the indexes of the pixels inside the circle index = (x - cx)**2 + (y - cy)**2 <= radius**2 imArr[:, :][index] = 255 # Call the "modified" method in order to update the viewer content im1.modified() input()
""" parser = OptionParser(usage="usage: %prog [options]", description=description) parser.add_option("-i", "--original_image", dest = "original_image", default = "resources/coins.JPG", help = "Input image filename.") parser.add_option("-s", "--step", dest = "step", type = "int", default = "25", help = "Grid step between two cell centers.(positive integer)" ) parser.add_option("-w", "--weight", dest = "weight", type = "float", default = "10", help = "Level of regularization (positive value). Weight of the distance function when added to the gradient.") parser.add_option("--filter_ori", dest="filter_ori", action="store_true", help = " Filtering option on the original image (boolean).") parser.add_option("--no-filter_ori", dest="filter_ori", action="store_false", help = " Filtering option on the original image (boolean).") parser.set_defaults(filter_ori = True) (options, args) = parser.parse_args() step = options.step weight = options.weight filter_ori = options.filter_ori image_file_name = options.original_image imin = sp.Image(image_file_name) imout, imgrad, imminima = demo_m_waterpixels(imin, step, weight, filter_ori) image = imout.getNumArray() image = image.transpose() imin = misc.imread(image_file_name) edges = filter.sobel(image) edges = color.rgb2gray(edges) out = edges limiar = 0 total_x = len(out) total_y = len(out[0]) for x in range(total_x): for y in range(total_y): if out[x][y] > limiar:
import smilPython as sm import numpy as np # read a 16 bits RAW Image file = "Slices-16.raw" im16 = sm.Image('UINT16') sp.readRAW(file, 700, 700, 700, im16) # Let's convert 8 bit input image # get a pointer to a numpy array p16 = im16.getNumArray() # scale pixel values from 2**16 to 2**8 p16 //= 256 # get a new 8 bit numpy array p8 = p.astype('uint8') # create a 8 bits image with the same dimensions of the 16 bit image im8 = sm.Image(im16, 'UINT8') # come back to Smil Image im8.fromNumArray(p8)
def demo_m_waterpixels(imin, step, d_weight, filter_ori): """ Compute m-waterpixels, i.e. superpixels based on the watershed transformation. Flooding starts form the best minimum of each cell of a regular grid. The gradient used to be flooded is regularized using the distance function to these minima. Cells of the grid are chosen here to be squares. Input : imin (image UINT8): original image, to be segmented into superpixels step (UINT8) : grid step, i.e. distance between two cell centers of the grid d_weight (UINT8) : constant to be multiplied with function distance before addition to gradient image. If d_weight <=0, then only the gradient is taken into account. filter_ori (BOOLEAN) : do we filter the input image? Output: image (UINT16) : labelled superpixels image (UINT8) : distance weighted gradient function image (UINT16) : minima used in the computation """ ##----------------------------------------------------------------------------------------- ##----------------------------------------------------------------------------------------- # Connexity: basicse = sp.CrossSE() gridse = sp.SquSE() # Ori filtering if filter_ori is True: my_area_filtering(imin, step*step/16) # Gradient computation im_grad = my_gradient(imin, basicse, True) ## Pool of working images: imwrk0 = sp.Image(im_grad) imwrk1 = sp.Image(im_grad, "UINT16") imwrk2 = sp.Image(im_grad, "UINT16") # Compute cell centers and cells size = imin.getSize() im_markers, im_cells = im_labelled_square_grid_points(size, step, step/6) ##----------------------------------------------------------------------------------------- ##----------------------------------------------------------------------------------------- ## Choice of the markers : one per grid cell ##----------------------------------------------------------------------------------------- ##----------------------------------------------------------------------------------------- # Step 1 : Computation of the minima of the gradient im_minima = sp.Image(im_grad) sp.minima(im_grad, im_minima, basicse) #Step 2 : Imposing minimum distance between minima (= Removing minima candidates which fall on cell margins ) sp.test(im_cells, im_minima, 0, imwrk0) sp.label(imwrk0, imwrk1, basicse) #Step 3 : Evaluation of the importance of minima ( = computation of their surfacic extinction) im_minima_val = sp.Image(imwrk1) sp.watershedExtinction( im_grad, imwrk1, im_minima_val, "a", basicse) # Step 4 : Taking back at value 2 the minima of null-volumic extinction sp.test( imwrk0, 2, 0, imwrk2) sp.test( im_minima_val, im_minima_val, imwrk2, im_minima_val ) # Step 5 : Coping with the potential absence of minimum in cells (= choosing the minimum value inside this cell as its marker if necessary) imwrk00=sp.Image(imwrk0) blobs = sp.computeBlobs(im_cells) sp.test(im_cells, im_grad, 0, imwrk00) minVals = sp.measMinVals(imwrk00, blobs) sp.applyLookup(im_cells, minVals, imwrk0) sp.test(imwrk00==imwrk0, 1, 0, imwrk1) maxVals = sp.measMaxVals(im_minima_val, blobs) sp.applyLookup(im_cells, maxVals, imwrk2) sp.test(imwrk2, im_minima_val, imwrk1, im_minima_val) # Step 6 : Selection of one marker per cell one_min_per_grid_cell(im_cells, blobs, im_minima_val, basicse) ##----------------------------------------------------------------------------------------- ##----------------------------------------------------------------------------------------- ## Spatial regularization of the gradient ##----------------------------------------------------------------------------------------- ##----------------------------------------------------------------------------------------- #Step 1 : Computation of the distance function to the markers immask = sp.Image(im_markers, "UINT8") sp.test(im_minima_val, 0, 1, immask) imdist = sp.Image(immask, "UINT8") sp.dist(immask, imdist, gridse) #Step 2 : Adding the distance function to the gradient if d_weight > 0: weight = d_weight * float(2)/step sp.mul(imdist, weight, imdist) sp.add(imdist, im_grad, im_grad) ##----------------------------------------------------------------------------------------- ##----------------------------------------------------------------------------------------- ## Superpixel segmentation : watershed transformation, flooding from selected minima on the regularized gradient ##----------------------------------------------------------------------------------------- ##----------------------------------------------------------------------------------------- sp.copy(im_minima_val, imwrk1) sp.label(imwrk1, im_minima_val, basicse) imout = sp.Image(im_minima_val) sp.basins(im_grad, im_minima_val, imout, basicse) ##----------------------------------------------------------------------------------------- ##----------------------------------------------------------------------------------------- return imout, im_grad, im_minima_val
def ImageFromArray(im_arr): im = smil.Image(*im_arr.shape[::-1]) im_np = im.getNumArray() im_np[:] = im_arr.transpose()[:] return im
import smilPython as sp import time thresh = 1000 im = sp.Image("https://smil.cmm.minesparis.psl.eu/images/balls.png") iml = sp.Image(im) img = sp.Image(im) ims = sp.Image(im) sp.label(im, iml) im.show("balls.png") iml.showLabel("iml") sp.areaThreshold(iml, thresh, True, img) img.showLabel("img") sp.areaThreshold(im, thresh, False, ims) ims.show("ims") nlold = 0 for threshold in range(1, 6000, 20): sp.areaThreshold(im, threshold, True, ims) nl = sp.label(ims, iml) if nl != nlold: print(' Threshold {:6d} : {:3d} blobs'.format(threshold, nl)) sp.Gui.processEvents() time.sleep(1) if nl == 0: break nlold = nl