def test_getbbox_no_args(): # Arrange p = ImagePath.Path([0, 1, 2, 3]) # Act / Assert with pytest.raises(TypeError): p.getbbox(1)
def test_invalid_coords(): # Arrange coords = ["a", "b"] # Act / Assert with pytest.raises(SystemError): ImagePath.Path(coords)
def test_path(): p = ImagePath.Path(list(range(10))) # sequence interface assert_equal(len(p), 5) assert_equal(p[0], (0.0, 1.0)) assert_equal(p[-1], (8.0, 9.0)) assert_equal(list(p[:1]), [(0.0, 1.0)]) assert_equal(list(p), [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0), (6.0, 7.0), (8.0, 9.0)]) # method sanity check assert_equal(p.tolist(), [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0), (6.0, 7.0), (8.0, 9.0)]) assert_equal(p.tolist(1), [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) assert_equal(p.getbbox(), (0.0, 1.0, 8.0, 9.0)) assert_equal(p.compact(5), 2) assert_equal(list(p), [(0.0, 1.0), (4.0, 5.0), (8.0, 9.0)]) p.transform((1, 0, 1, 0, 1, 1)) assert_equal(list(p), [(1.0, 2.0), (5.0, 6.0), (9.0, 10.0)]) # alternative constructors p = ImagePath.Path([0, 1]) assert_equal(list(p), [(0.0, 1.0)]) p = ImagePath.Path([0.0, 1.0]) assert_equal(list(p), [(0.0, 1.0)]) p = ImagePath.Path([0, 1]) assert_equal(list(p), [(0.0, 1.0)]) p = ImagePath.Path([(0, 1)]) assert_equal(list(p), [(0.0, 1.0)]) p = ImagePath.Path(p) assert_equal(list(p), [(0.0, 1.0)]) p = ImagePath.Path(p.tolist(0)) assert_equal(list(p), [(0.0, 1.0)]) p = ImagePath.Path(p.tolist(1)) assert_equal(list(p), [(0.0, 1.0)]) p = ImagePath.Path(array.array("f", [0, 1])) assert_equal(list(p), [(0.0, 1.0)]) p = ImagePath.Path(array.array("f", [0, 1]).tostring()) assert_equal(list(p), [(0.0, 1.0)])
def test_path_odd_number_of_coordinates(): # Arrange coords = [0] # Act / Assert with pytest.raises(ValueError) as e: ImagePath.Path(coords) assert str(e.value) == "wrong number of coordinates"
def test_invalid_coords(): # Arrange coords = ["a", "b"] # Act / Assert with pytest.raises(ValueError) as e: ImagePath.Path(coords) assert str(e.value) == "incorrect coordinate type"
def test_map(coords, expected): # Arrange p = ImagePath.Path(coords) # Act # Modifies the path in-place p.map(lambda x, y: (x * 2, y * 3)) # Assert assert list(p) == expected
def draw_linestring(draw_ctx, antialias, color, linestring, merc_center, zoom, img_size): vectors = [] for point in linestring: coord = Coords(point[0], point[1]) merc_point = transform_to_mercator(coord, zoom) img_coord = convert_to_img_coords(merc_center, merc_point, img_size, 1) vectors.append((img_coord[0] * antialias, img_coord[1] * antialias)) draw_ctx.line(ImagePath.Path(vectors), color, 10)
def cropImage(imgPath, label, coordinates): if len(coordinates) != 0: pixels = [] for coordinate in coordinates: x = (float)(coordinate.split(',')[0]) y = (float)(coordinate.split(',')[1]) pixels.append((x, y)) im = Image.open(imgPath) contour = ImagePath.Path(pixels) minimalBound = contour.getbbox() im = im.crop(minimalBound) im.save(imgPath)
def test_transform(): # Arrange p = ImagePath.Path([0, 1, 2, 3]) theta = math.pi / 15 # Act # Affine transform, in-place p.transform((math.cos(theta), math.sin(theta), 20, -math.sin(theta), math.cos(theta), 20), ) # Assert assert p.tolist() == [ (20.20791169081776, 20.978147600733806), (22.58003027392089, 22.518619420565898), ]
def __init__(self, population_size, polygon_number, original_image): self.max_coordinate = min(original_image.size[0], original_image.size[1]) self.coordinate_range = [original_image.size[0], original_image.size[1]] self.original_image = original_image.convert('RGBA') self.original_image_array = np.array(original_image) self.size = original_image.size self.candidate_array = np.zeros((self.size[0], self.size[1], 4)) self.population_size = population_size self.polygon_number = polygon_number self.mutation_rate = 0.5 new_image = ImagePath.Path(((0,0),(0,self.coordinate_range[1]),(self.coordinate_range[0],self.coordinate_range[1]),(self.coordinate_range[0],0))).getbbox() #hardcoded for MonaLisa pic size = list(map(int, map(math.ceil, new_image[2:]))) self.test_img = Image.new("RGBA", size) self.background = Image.new("RGBA", size, (255,0,0,0)) self.random_initialization(population_size, polygon_number)
def make_object(N, min_indexes, max_indexes): """ returns: amplitude, phase both with normalized values between 0 and 1 """ # must be divisible by 4 assert N % 4 == 0 obj = np.zeros((N, N), dtype=np.complex128) min_x = N / 4 + 1 min_y = N / 4 + 1 max_x = N - N / 4 - 1 max_y = N - N / 4 - 1 # generate random indexes # np.random.seed(3367) indexes_n = np.random.randint(min_indexes, max_indexes) # for each index generate an x and y point x = [] y = [] for i in range(indexes_n): x_val = min_x + np.random.rand(1) * (max_x - min_x) y_val = min_y + np.random.rand(1) * (max_y - min_y) x.append(int(x_val)) y.append(int(y_val)) x.append(x[0]) y.append(y[0]) xy = [(x_, y_) for x_, y_ in zip(x, y)] image = ImagePath.Path(xy).getbbox() size = list(map(int, map(math.ceil, image[2:]))) img = Image.new("RGB", [N, N], "#000000") img1 = ImageDraw.Draw(img) img1.polygon(xy, fill="#ffffff") # convert to numpy array amplitude = np.array(img.getdata(), dtype=np.uint8).reshape(N, N, -1) amplitude = np.sum(amplitude, axis=2) amplitude = amplitude / np.max(amplitude) # apply gaussian filter amplitude = gaussian_filter(amplitude, sigma=0.8, order=0) return amplitude
def test_transform_with_wrap(): # Arrange p = ImagePath.Path([0, 1, 2, 3]) theta = math.pi / 15 # Act # Affine transform, in-place, with wrap parameter p.transform( (math.cos(theta), math.sin(theta), 20, -math.sin(theta), math.cos(theta), 20), 1.0, ) # Assert assert p.tolist() == [ (0.20791169081775962, 20.978147600733806), (0.5800302739208902, 22.518619420565898), ]
def coordinate(): side = random.randint(3, 6) # 坐标加1把单位圆从原点移动到第一象限 xy = [(math.cos(th) + 1, math.sin(th) + 1) for th in [s * (2 * math.pi) / side for s in range(side)]] loc, scale = 75, 10 x_scale, y_scale = random.normal(loc, scale), random.normal(loc, scale) x_shift, y_shift = random.uniform(0, 800), random.uniform(0, 800) xy = list( map( lambda coords: (coords[0] * x_scale + x_shift, coords[1] * y_scale + y_shift), xy)) if random.randn() > 0.25: return ImagePath.Path(xy).getbbox() return xy
def drawPatch(self, pos, turn, invert, type, draw, size, foreColor, backColor): """ @param size patch size """ path = self.PATH_SET[type] if not path: # blank patch invert = not invert path = [(0., 0.), (1., 0.), (1., 1.), (0., 1.), (0., 0.)] patch = ImagePath.Path(path) if invert: foreColor, backColor = backColor, foreColor mat = Matrix2D.rotateSquare(turn, pivot=(0.5, 0.5)) * \ Matrix2D.translate(*pos) * \ Matrix2D.scale(size, size) patch.transform(mat.for_PIL()) draw.rectangle((pos[0] * size, pos[1] * size, (pos[0] + 1) * size, (pos[1] + 1) * size), fill=backColor) draw.polygon(patch, fill=foreColor, outline=foreColor)
def render(self, op, xy, pen, brush=None): # handle color arguments outline = fill = None width = 1 if isinstance(pen, Pen): outline = pen.color width = pen.width elif isinstance(brush, Pen): outline = brush.color width = brush.width if isinstance(brush, Brush): fill = brush.color elif isinstance(pen, Brush): fill = pen.color # handle transformation if self.transform: xy = ImagePath.Path(xy) xy.transform(self.transform) # render the item if op == "line": self.draw.line(xy, fill=outline, width=width) else: getattr(self.draw, op)(xy, fill=fill, outline=outline)
def test_getbbox(coords, expected): # Arrange p = ImagePath.Path(coords) # Act / Assert assert p.getbbox() == expected
def as_raster(self, *args): ''' Group 1: Variant 1: refraster, pixeltype, [value=1, nodataval=0] Group 2: Variant 2: ... Variant 3: scalex, scaley, pixeltype, [value=1, nodataval=0, upperleftx=NULL, upperlefty=NULL, skewx=0, skewy=0] Group 3: Variant 4: ... Variant 5: width, height, pixeltype, [value=1, nodataval=0, upperleftx=NULL, upperlefty=NULL, skewx=0, skewy=0 ''' from ..raster.raster import Raster, make_empty_raster # parse args def getarg(args, pos, default): if len(args) >= (pos+1): val = args[pos] if val is None: val = default else: val = default return val # GROUP 1: existing raster if not isinstance(args[0], (float,int)): # raster ref, text pixeltype, double precision value=1, double precision nodataval=0, boolean touched=false if isinstance(args[0], Raster): ref = args[0] else: ref = Raster(args[0]) pixeltype = args[1] value = getarg(args, 2, 1) nodataval = getarg(args, 3, 0) # GROUP 2: set params, autocalc width/height elif isinstance(args[0], float) and isinstance(args[2], float): ## # double precision scalex, double precision scaley, double precision gridx, double precision gridy, text pixeltype, double precision value=1, double precision nodataval=0, double precision skewx=0, double precision skewy=0, boolean touched=false ## # aligns upperleft to gridx/y scaleX,scaleY,gridX,gridY = args[:4] pixeltype = args[4] value = getarg(args, 5, 1) nodataval = getarg(args, 6, 0) skewX = getarg(args, 7, 0.0) skewY = getarg(args, 8, 0.0) xmin,ymin,xmax,ymax = self.bbox() width = abs(xmax-xmin) / float(scaleX) height = abs(ymax-ymin) / float(scaleY) width = int(round(abs(width))) height = int(round(abs(height))) from affine import Affine upperLeftX = xmin if scaleX > 0 else xmax upperLeftY = ymin if scaleY > 0 else ymax aff = Affine(scaleX,skewX,upperLeftX, skewY,scaleY,upperLeftY) gridCol,gridRow = (~aff) * (gridX,gridY) # predict pixel of gridx,gridy gridX2,gridY2 = aff * (math.floor(gridCol), math.floor(gridRow)) # use whole pixel to predict gridx,gridy upperLeftX,upperLeftY = upperLeftX - (gridX2-gridX), upperLeftY - (gridY2-gridY) # use actual and predicted gridx,gridy to adjust upperleft geom extent #print 'bbox',xmin,ymin,xmax,ymax #print 'grid align',gridX,gridY,gridCol,gridRow,gridX2,gridY2 #print 'asrast params',width, height, upperLeftX, upperLeftY, scaleX, scaleY, skewX, skewY ref = make_empty_raster(width, height, upperLeftX, upperLeftY, scaleX, scaleY, skewX, skewY) elif isinstance(args[0], float) and isinstance(args[2], basestring): # double precision scalex, double precision scaley, text pixeltype, double precision value=1, double precision nodataval=0, double precision upperleftx=NULL, double precision upperlefty=NULL, double precision skewx=0, double precision skewy=0, boolean touched=false # uses upperleft scaleX,scaleY,pixeltype = args[:3] value = getarg(args, 3, 1) nodataval = getarg(args, 4, 0) xmin,ymin,xmax,ymax = self.bbox() upperLeftX = getarg(args, 5, xmin) upperLeftY = getarg(args, 6, ymax) # flipped y by default skewX = getarg(args, 7, 0.0) skewY = getarg(args, 8, 0.0) width = abs(xmax-xmin) / float(scaleX) height = abs(ymax-ymin) / float(scaleY) width = int(round(abs(width))) height = int(round(abs(height))) ref = make_empty_raster(width, height, upperLeftX, upperLeftY, scaleX, scaleY, skewX, skewY) # GROUP 3: set width/height, autocalc params elif isinstance(args[0], int) and isinstance(args[2], float): # integer width, integer height, double precision gridx, double precision gridy, text pixeltype, double precision value=1, double precision nodataval=0, double precision skewx=0, double precision skewy=0, boolean touched=false # aligns upperleft to gridx/y width,height,gridX,gridY = args[:4] pixeltype = args[4] value = getarg(args, 5, 1) nodataval = getarg(args, 6, 0) skewX = getarg(args, 7, 0.0) skewY = getarg(args, 8, 0.0) xmin,ymin,xmax,ymax = self.bbox() scaleX = abs(xmax-xmin) / float(width) scaleY = abs(ymax-ymin) / float(height) * -1 # flipped y by default (since we only width,height,upperleft, no way to know what direction crs goes) from affine import Affine upperLeftX = xmin if scaleX > 0 else xmax upperLeftY = ymin if scaleY > 0 else ymax aff = Affine(scaleX,skewX,upperLeftX, skewY,scaleY,upperLeftY) gridCol,gridRow = (~aff) * (gridX,gridY) # predict pixel of gridx,gridy gridX2,gridY2 = aff * (math.floor(gridCol), math.floor(gridRow)) # use whole pixel to predict gridx,gridy upperLeftX,upperLeftY = upperLeftX - (gridX2-gridX), upperLeftY - (gridY2-gridY) # use actual and predicted gridx,gridy to adjust upperleft geom extent ref = make_empty_raster(width, height, upperLeftX, upperLeftY, scaleX, scaleY, skewX, skewY) elif isinstance(args[0], int) and isinstance(args[2], basestring): # integer width, integer height, text pixeltype, double precision value=1, double precision nodataval=0, double precision upperleftx=NULL, double precision upperlefty=NULL, double precision skewx=0, double precision skewy=0, boolean touched=false # uses upperleft width,height,pixeltype = args[:3] value = getarg(args, 3, 1) nodataval = getarg(args, 4, 0) xmin,ymin,xmax,ymax = self.bbox() upperLeftX = getarg(args, 5, xmin) upperLeftY = getarg(args, 6, ymax) # flipped y by default skewX = getarg(args, 7, 0.0) skewY = getarg(args, 8, 0.0) scaleX = abs(xmax-xmin) / float(width) scaleY = abs(ymax-ymin) / float(height) * -1 # flipped y by default ref = make_empty_raster(width, height, upperLeftX, upperLeftY, scaleX, scaleY, skewX, skewY) else: raise Exception('Invalid function args: {}'.format(args)) # create drawer import numpy as np from PIL import Image,ImageDraw,ImagePath mode = {'b1':'1', 'u1':'L', 'i4':'I', 'f8':'F'}[pixeltype] img = Image.new(mode, (ref.width, ref.height), nodataval) drawer = ImageDraw.Draw(img) # get the raster's inverse affine to use for drawing a,b,c,d,e,f,_,_,_ = list(~ref._affine) # set burn values fill = value outline = None holefill = nodataval holeoutline = None #print ["burnmain",fill,outline,"burnhole",holefill,holeoutline] # make all multis so can treat all same geoj = self.as_GeoJSON() geotype = geoj['type'] coords = geoj["coordinates"] if not "Multi" in geotype: coords = [coords] # polygon, basic black fill, no outline if "Polygon" in geotype: for poly in coords: # exterior exterior = [tuple(p) for p in poly[0]] path = ImagePath.Path(exterior) #print list(path)[:10] path.transform((a,b,c,d,e,f)) #print list(path)[:10] drawer.polygon(path, fill=fill, outline=outline) # holes if len(poly) > 1: for hole in poly[1:]: hole = [tuple(p) for p in hole] path = ImagePath.Path(hole) path.transform((a,b,c,d,e,f)) drawer.polygon(path, fill=holefill, outline=holeoutline) # line, 1 pixel line thickness elif "LineString" in geotype: for line in coords: path = ImagePath.Path(line) path.transform((a,b,c,d,e,f)) drawer.line(path, fill=fill) # point, 1 pixel square size elif "Point" in geotype: path = ImagePath.Path(coords) path.transform((a,b,c,d,e,f)) drawer.point(path, fill=fill) # make raster from drawn img out = make_empty_raster(ref) out._load_header() arr = np.array(img) # TODO: prob outsource to builtin add_band() method wkb = out._wkb.tobytes() dtypes = ['b1', 'u1', 'u1', 'i1', 'u1', 'i2', 'u2', 'i4', 'u4', 'f4', 'f8'] pixeltypenum = dtypes.index(pixeltype) bandheader = {'isOffline': False, 'hasNodataValue': True, 'isNodataValue': False, # maybe check? 'pixtype': pixeltypenum, 'nodata': nodataval, } wkb += out._write_band_header(bandheader) wkb += arr.tostring() wkb_mem = memoryview(wkb) rast = Raster(wkb_mem) return rast
def text(self, xy, text, font): if self.transform: xy = ImagePath.Path(xy) xy.transform(self.transform) self.draw.text(xy, text, font=font.font, fill=font.color)
import math import typing from abc import ABC, abstractmethod from typing import overload # noinspection PyPackageRequirements from PIL import ImagePath from x7.lib.iters import iter_rotate from .typing import * Points = Iterable[Union['BasePoint', Number, Tuple[Number, Number]]] PointList = List['BasePoint'] PointUnionList = List[Union['BasePoint', Tuple[float, float]]] PointTFUnionList = List[Union['BasePoint', float, Tuple[float, float]]] ImagePathType = type(ImagePath.Path([])) XYTuple = Tuple[float, float] XYList = List[XYTuple] PointOrXYList = Union[PointList, XYList] __all__ = [ 'BBox', 'BasePoint', 'ImagePathType', 'Line', 'ParallelLineError', 'Point', 'PointCalc', 'PointRelative', 'PointList', 'PointOrXYList',
def test_path(self): p = ImagePath.Path(list(range(10))) # sequence interface self.assertEqual(len(p), 5) self.assertEqual(p[0], (0.0, 1.0)) self.assertEqual(p[-1], (8.0, 9.0)) self.assertEqual(list(p[:1]), [(0.0, 1.0)]) with self.assertRaises(TypeError) as cm: p['foo'] self.assertEqual(str(cm.exception), "Path indices must be integers, not str") self.assertEqual(list(p), [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0), (6.0, 7.0), (8.0, 9.0)]) # method sanity check self.assertEqual(p.tolist(), [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0), (6.0, 7.0), (8.0, 9.0)]) self.assertEqual(p.tolist(1), [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) self.assertEqual(p.getbbox(), (0.0, 1.0, 8.0, 9.0)) self.assertEqual(p.compact(5), 2) self.assertEqual(list(p), [(0.0, 1.0), (4.0, 5.0), (8.0, 9.0)]) p.transform((1, 0, 1, 0, 1, 1)) self.assertEqual(list(p), [(1.0, 2.0), (5.0, 6.0), (9.0, 10.0)]) # alternative constructors p = ImagePath.Path([0, 1]) self.assertEqual(list(p), [(0.0, 1.0)]) p = ImagePath.Path([0.0, 1.0]) self.assertEqual(list(p), [(0.0, 1.0)]) p = ImagePath.Path([0, 1]) self.assertEqual(list(p), [(0.0, 1.0)]) p = ImagePath.Path([(0, 1)]) self.assertEqual(list(p), [(0.0, 1.0)]) p = ImagePath.Path(p) self.assertEqual(list(p), [(0.0, 1.0)]) p = ImagePath.Path(p.tolist(0)) self.assertEqual(list(p), [(0.0, 1.0)]) p = ImagePath.Path(p.tolist(1)) self.assertEqual(list(p), [(0.0, 1.0)]) p = ImagePath.Path(array.array("f", [0, 1])) self.assertEqual(list(p), [(0.0, 1.0)]) arr = array.array("f", [0, 1]) if hasattr(arr, 'tobytes'): p = ImagePath.Path(arr.tobytes()) else: p = ImagePath.Path(arr.tostring()) self.assertEqual(list(p), [(0.0, 1.0)])
def test_path(): p = ImagePath.Path(list(range(10))) # sequence interface assert len(p) == 5 assert p[0] == (0.0, 1.0) assert p[-1] == (8.0, 9.0) assert list(p[:1]) == [(0.0, 1.0)] with pytest.raises(TypeError) as cm: p["foo"] assert str(cm.value) == "Path indices must be integers, not str" assert list(p) == [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0), (6.0, 7.0), (8.0, 9.0)] # method sanity check assert p.tolist() == [ (0.0, 1.0), (2.0, 3.0), (4.0, 5.0), (6.0, 7.0), (8.0, 9.0), ] assert p.tolist(1) == [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] assert p.getbbox() == (0.0, 1.0, 8.0, 9.0) assert p.compact(5) == 2 assert list(p) == [(0.0, 1.0), (4.0, 5.0), (8.0, 9.0)] p.transform((1, 0, 1, 0, 1, 1)) assert list(p) == [(1.0, 2.0), (5.0, 6.0), (9.0, 10.0)] # alternative constructors p = ImagePath.Path([0, 1]) assert list(p) == [(0.0, 1.0)] p = ImagePath.Path([0.0, 1.0]) assert list(p) == [(0.0, 1.0)] p = ImagePath.Path([0, 1]) assert list(p) == [(0.0, 1.0)] p = ImagePath.Path([(0, 1)]) assert list(p) == [(0.0, 1.0)] p = ImagePath.Path(p) assert list(p) == [(0.0, 1.0)] p = ImagePath.Path(p.tolist(0)) assert list(p) == [(0.0, 1.0)] p = ImagePath.Path(p.tolist(1)) assert list(p) == [(0.0, 1.0)] p = ImagePath.Path(array.array("f", [0, 1])) assert list(p) == [(0.0, 1.0)] arr = array.array("f", [0, 1]) if hasattr(arr, "tobytes"): p = ImagePath.Path(arr.tobytes()) else: p = ImagePath.Path(arr.tostring()) assert list(p) == [(0.0, 1.0)]