diff --git a/src/SimNDT/core/scenario.py b/src/SimNDT/core/scenario.py new file mode 100644 index 0000000..070515a --- /dev/null +++ b/src/SimNDT/core/scenario.py @@ -0,0 +1,289 @@ +__author__ = 'Miguel Molero' + + +import numpy as np +from scipy.misc import imread, imrotate + +from SimNDT.core.constants import * +from SimNDT.core.boundary import Boundary + + +class Scenario: + + def __init__(self, Width = 40, Height = 40, Pixel_mm =10, Label=0): + self.Width = Width + self.Height = Height + self.Pixel_mm = Pixel_mm + self.Label = Label + + self.M = int(self.Height * self.Pixel_mm) + self.N = int(self.Width * self.Pixel_mm) + self.I = np.ones((self.M,self.N), dtype=np.uint8)*Label # create a matrix of MxN with each pixel having value as material Label + self.Iabs = 0 + self.Io = np.ones((self.M,self.N), dtype=np.uint8)*Label + self.Tap = list() + + self.BC = False + + # print("Scenario Width="+str(Width)+" Height="+str(Height)+" M="+str(self.M)+" N="+str(self.N)+" Pixel_mm="+str(Pixel_mm)+" Label="+str(Label)) + + + def setImage(self,I, Width, Height, Pixel_mm, Label): + self.I = np.copy(I).astype(np.uint8) + self.Io = np.copy(I).astype(np.uint8) + self.Width = Width + self.Height = Height + self.Pixel_mm = Pixel_mm + self.Label = Label + self.M = int(self.Height * self.Pixel_mm) + self.N = int(self.Width * self.Pixel_mm) + + self.resetBoundary() + + + def resetBoundary(self): + self.Iabs = 0 + self.Tap = list() + self.BC = False + + def __str__(self): + return ("Scenario: Width={}, Height={}, Pixel_mm={}, Label={}, M={}, N={}, I.shape={}, Iabs.shape={}, " + "Io.shape={}, Tap={}, BC={}").format( + self.Width, self.Height, self.Pixel_mm, self.Label, self.M, self.N, self.I.shape, + self.Iabs.shape if isinstance(self.Iabs, np.ndarray) else self.Iabs, + self.Io.shape, self.Tap, self.BC) + + def __repr__(self): + return "Scenario(Width={}, Height={}, Pixel_mm={}, Label={})".format( + self.Width, self.Height, self.Pixel_mm, self.Label) + + + + def createBoundaries(self,boundaries): + self.M, self.N = np.shape(self.I) + self.Width = int(self.N/float(self.Pixel_mm)) + self.Height = int(self.N/float(self.Pixel_mm)) + self.resetBoundary() + + for boundary in boundaries: + if boundary.BC == BC.AirLayer: + size = 1 + else: + size = boundary.Size * self.Pixel_mm + + if boundary.Name == "Top": + topSize = size + elif boundary.Name == "Bottom": + bottomSize = size + elif boundary.Name == "Left": + leftSize = size + elif boundary.Name == "Right": + rightSize = size + + self.Tap = np.array([topSize, bottomSize, leftSize, rightSize]) + self.Iabs = self.applyBoundaries(self.I) + self.BC = True + + + def applyBoundaries(self, I): + + self.Tap = np.int32(self.Tap) + M_abs = int( self.M + self.Tap[0] + self.Tap[1] ) + N_abs = int( self.N + self.Tap[2] + self.Tap[3] ) + + Iabs = 255*np.ones((int(M_abs),int(N_abs)),dtype=np.uint8) + Iabs[self.Tap[0] : M_abs-self.Tap[1], self.Tap[2] : N_abs-self.Tap[3]] = np.copy(I) + return Iabs + + + def updateScenario(self): + if self.BC: + self.Iabs = self.applyBoundaries(self.I) + + + def addEllipse(self, x0, y0, a, b, theta, Label): + + x0 *= self.Pixel_mm + y0 *= self.Pixel_mm + a *= self.Pixel_mm + b *= self.Pixel_mm + + (x,y) = np.meshgrid(range(0,self.N),range(0,self.M)) + + Ellipse = ( ( ( (x-x0)*np.cos(theta)+(y-y0)*np.sin(theta) )**2 )/(a**2) + + ( ( (x-x0)*np.sin(theta)-(y-y0)*np.cos(theta) )**2 )/(b**2) ) + + Img = (Ellipse < 1.0) + indx,indy = np.nonzero(Img == 1) + self.I[indx,indy] = Label + + self.updateScenario() + + + def resetImage(self): + + self.resetBoundary() + self.I = np.copy(self.Io) + + + + def addObject(self, obj): + + if obj.Name == "ellipse": + print("Adding ellipse to Scenario.") + a = obj.a + b = obj.b + theta = obj.theta + Label = obj.Label + # x0 = obj.x0 * self.Pixel_mm + # y0 = obj.y0 * self.Pixel_mm + x0 = obj.x0 + y0 = obj.y0 + self.addEllipse(x0, y0, a, b, theta, Label) + + + elif obj.Name == "circle": + print("Adding circle to Scenario.") + x0 = obj.x0 + y0 = obj.y0 + a = obj.r + Label = obj.Label + self.addEllipse(x0, y0, a, a, 0, Label) + + + elif obj.Name == "square": + print("Adding square to Scenario.") + x0 = obj.x0 + y0 = obj.y0 + L = obj.L + theta = obj.theta + Label = obj.Label + self.addRectangle(x0, y0, L, L, theta, Label) + + elif obj.Name == "rectangle": + print("Adding rectangle to Scenario.") + x0 = obj.x0 + y0 = obj.y0 + W = obj.W + H = obj.H + theta = obj.theta + Label = obj.Label + self.addRectangle(x0, y0, W, H, theta, Label) + + # @blab+ + # Make a copy of I, just for visualization (I is graphics view and material matrix for EDIF) + def addTransducer(self, x0, y0, Size, Label): + ox = 0 + oy = 0 + if len(self.Tap) != 0: + ox = self.Tap[2] + oy = self.Tap[0] + x0 = x0+ox + y0 = y0+oy + a = Size + b = a + theta = 0 + x0 *= self.Pixel_mm + y0 *= self.Pixel_mm + a *= self.Pixel_mm + b *= self.Pixel_mm + + (x,y) = np.meshgrid(range(0,self.N),range(0,self.M)) + + Ellipse = ( ( ( (x-x0)*np.cos(theta)+(y-y0)*np.sin(theta) )**2 )/(a**2) + + ( ( (x-x0)*np.sin(theta)-(y-y0)*np.cos(theta) )**2 )/(b**2) ) + Img = (Ellipse < 1.0) + if np.size(self.Iabs)==1: + I = np.copy(self.I) + else: + I = np.copy(self.Iabs) + indx,indy = np.nonzero(Img == 1) + I[indx,indy] = Label + return I + + def addSensor(self, I, x0, y0, Size, Label): + ox = 0 + oy = 0 + if len(self.Tap) != 0: + ox = self.Tap[2] + oy = self.Tap[0] + x0 = x0+ox + y0 = y0+oy + + a = Size + b = a + theta = 0 + x0 *= self.Pixel_mm + y0 *= self.Pixel_mm + a *= self.Pixel_mm + b *= self.Pixel_mm + + (x,y) = np.meshgrid(range(0,self.N),range(0,self.M)) + + Ellipse = ( ( ( (x-x0)*np.cos(theta)+(y-y0)*np.sin(theta) )**2 )/(a**2) + + ( ( (x-x0)*np.sin(theta)-(y-y0)*np.cos(theta) )**2 )/(b**2) ) + + Img = (Ellipse < 1.0) + indx,indy = np.nonzero(Img == 1) + I[indx,indy] = Label + return I + + + def addRectangle(self, W_0, H_0, W, H, Theta,Label): + """ + Create a rectangle + W_0, H_0: center of rectangle + W,H : dimension of rectangle + """ + + a = round(H*self.Pixel_mm/2.0) + b = round(W*self.Pixel_mm/2.0) + angle = Theta * np.pi/180.0 + H0 = H_0*self.Pixel_mm + W0 = W_0*self.Pixel_mm + + if angle == 0: + size_a = 4*a + size_b = 4*b + + vectX = np.int32(np.linspace(-a,a, size_a) + H0) + vectY = np.int32(np.linspace(-b,b, size_b) + W0) + for x in vectX: + for y in vectY: + self.I[x, y] = Label + + else: + size_a = 4*a + size_b = 4*b + + for x in np.linspace(-a,a,size_a): + for y in np.linspace(-b,b,size_b): + _xr = np.int32(np.cos(angle)*x - np.sin(angle)*y + H0) + _yr = np.int32(np.sin(angle)*x + np.cos(angle)*y + W0) + self.I[_xr,_yr] = Label + + self.updateScenario() + + + def rotate(self, angle=90, direction="clockwise"): + if direction == "clockwise": + self.I = imrotate(self.I,-1*angle, interp = 'nearest') + self.M, self.N = np.shape(self.I) + + if np.size(self.Iabs) > 1: + self.Iabs = imrotate(self.Iabs,-1*angle, interp = 'nearest') + + else: + self.I = imrotate(self.I,angle, interp = 'nearest') + self.M, self.N = np.shape(self.I) + + if np.size(self.Iabs) > 1: + self.Iabs = imrotate(self.Iabs,angle, interp = 'nearest') + + + + + + + +