Public functions
width
Return the width (int) of the image.
View Source
@property
def width(self):
"""Return the width (int) of the image."""
w = self.shape[1]
return w
height
Return the height (int) of the image.
View Source
@property
def height(self):
"""Return the height (int) of the image."""
h = self.shape[0]
return h
channel
Return the number of channels (int) of the image.
View Source
@property
def channel(self):
"""Return the number of channels (int) of the image."""
if len(self.shape) > 2:
_, _, c = self.shape
else:
c = 0
return c
center
Return the position tuple(x, y) of the center of the image.
View Source
@property
def center(self):
"""Return the position tuple(x, y) of the center of the image."""
w, h = self.size()
return (w // 2, h // 2)
size
Return the size of the image as tuple(width, height).
View Source
def size(self):
"""Return the size of the image as tuple(width, height)."""
h, w = self.shape[:2]
return (w, h)
euclidian_distance
Return the euclidian distance with the image.
Parameters
- other: (sppasImage) an image with the same shape
View Source
def euclidian_distance(self, other):
"""Return the euclidian distance with the image.
:param other: (sppasImage) an image with the same shape
"""
w, h = self.size()
d = numpy.linalg.norm(self - other, axis=1)
return sum(sum(d)) / (w * h * 3)
get_proportional_size
Return the size of the image or a proportional size.
Parameters
- width: (int) Force the image to the width
- height: (int) Force the image to the height
Returns
- tuple(int, int) Width and height
View Source
def get_proportional_size(self, width=0, height=0):
"""Return the size of the image or a proportional size.
:param width: (int) Force the image to the width
:param height: (int) Force the image to the height
:return: tuple(int, int) Width and height
"""
if len(self) == 0:
return (0, 0)
width = sppasCoords.to_dtype(width)
height = sppasCoords.to_dtype(height)
if width < 0:
raise NegativeValueError(width)
if height < 0:
raise NegativeValueError(height)
h, w = self.shape[:2]
if width + height == 0:
return (w, h)
prop_width = prop_height = 0
propw = proph = 1.0
if width != 0:
prop_width = width
propw = float(width) / float(w)
if height != 0:
prop_height = height
proph = float(height) / float(h)
if width == 0:
prop_width = int(float(w) * proph)
if height == 0:
prop_height = int(float(h) * propw)
return (prop_width, prop_height)
surround_coord
Add a square surrounding the given coordinates.
Parameters
- coord: (sppasCoords) Area to surround
- color: (int, int, int) Rectangle color or brightness (if grayscale image).
- thickness: (int) Thickness of lines that make up the rectangle. Negative values, like CV_FILLED , mean that the function has to draw a filled rectangle.
- text: (str) Add text
View Source
def surround_coord(self, coord, color, thickness, text=''):
"""Add a square surrounding the given coordinates.
:param coord: (sppasCoords) Area to surround
:param color: (int, int, int) Rectangle color or brightness (if grayscale image).
:param thickness: (int) Thickness of lines that make up the rectangle.
Negative values, like CV_FILLED , mean that the function has to
draw a filled rectangle.
:param text: (str) Add text
"""
coord = sppasCoords.to_coords(coord)
cv2.rectangle(self, (coord.x, coord.y), (coord.x + coord.w, coord.y + coord.h), color, thickness)
if len(text) > 0:
h, w = self.shape[:2]
font_scale = float(w * h) / (1920.0 * 1080.0)
th = abs(thickness // 2)
text_size = cv2.getTextSize(text, fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=font_scale * 2, thickness=th)
if thickness < 0:
r, g, b = color
r = (r + 128) % 255
g = (g + 128) % 255
b = (b + 128) % 255
color = (r, g, b)
cv2.putText(self, text, (coord.x + 3 * th, coord.y + 3 * th + text_size[1]), cv2.FONT_HERSHEY_SIMPLEX, font_scale, color, th)
put_text
Put a text at the given coords.
Parameters
- coord: (sppasCoords) Area to put the text
- color: (int, int, int) Rectangle color or brightness (if grayscale image).
- thickness: (int) Thickness of lines that make up the rectangle. Negative values, like CV_FILLED , mean that the function has to draw a filled rectangle.
- text: (str) Add text
View Source
def put_text(self, coord, color, thickness, text):
"""Put a text at the given coords.
:param coord: (sppasCoords) Area to put the text
:param color: (int, int, int) Rectangle color or brightness (if grayscale image).
:param thickness: (int) Thickness of lines that make up the rectangle.
Negative values, like CV_FILLED , mean that the function has to
draw a filled rectangle.
:param text: (str) Add text
"""
w, _ = self.size()
coord = sppasCoords.to_coords(coord)
font_scale = max(1.0, float(w) / 1024.0)
if thickness < 0:
r, g, b = color
r = (r + 128) % 255
g = (g + 128) % 255
b = (b + 128) % 255
color = (r, g, b)
cv2.putText(self, text, (coord.x, coord.y), cv2.FONT_HERSHEY_DUPLEX, font_scale, color, thickness)
surround_point
Add a circle surrounding the given point.
Parameters
- point: (sppasCoords, list, tuple) (x,y) values to surround
- color: (int, int, int) Rectangle color or brightness (if grayscale image).
- thickness: (int) Thickness of lines that make up the rectangle. Negative values, like CV_FILLED , mean that the function has to draw a filled rectangle.
- radius: (int) Radius of the circle
View Source
def surround_point(self, point, color, thickness, radius=None):
"""Add a circle surrounding the given point.
:param point: (sppasCoords, list, tuple) (x,y) values to surround
:param color: (int, int, int) Rectangle color or brightness (if grayscale image).
:param thickness: (int) Thickness of lines that make up the rectangle.
Negative values, like CV_FILLED , mean that the function has to
draw a filled rectangle.
:param radius: (int) Radius of the circle
"""
if isinstance(point, sppasCoords) is False:
if isinstance(point, (tuple, list)) and len(point) >= 2:
try:
point = sppasCoords(point[0], point[1])
except Exception:
pass
if isinstance(point, sppasCoords) is False:
sppasTypeError(point, 'sppasCoords, tuple, list')
thickness = max(2, thickness)
if radius is None:
radius = thickness // 2
x = point.x - radius
y = point.y - radius
cv2.circle(self, (x, y), radius, color, thickness)
blank_image
Create and return an image with black pixels only.
Parameters
- w: (int) Image width. 0 means to use the current image width.
- h: (int) Image height. 0 means to use the current height.
- white: (bool) Return a white image instead of a black one.
- alpha: (int | None) Add alpha channel with the given int value
- dtype: (numpy.dtype) Image data type
Returns
- (sppasImage) Fully black BGR image
View Source
def blank_image(self, w=0, h=0, white=False, alpha=None, dtype=numpy.uint8):
"""Create and return an image with black pixels only.
:param w: (int) Image width. 0 means to use the current image width.
:param h: (int) Image height. 0 means to use the current height.
:param white: (bool) Return a white image instead of a black one.
:param alpha: (int | None) Add alpha channel with the given int value
:param dtype: (numpy.dtype) Image data type
:return: (sppasImage) Fully black BGR image
"""
if w < 0:
raise NegativeValueError(w)
if h < 0:
raise NegativeValueError(h)
if w == 0:
w = self.width
if h == 0:
h = self.height
t = (h, w, 3)
nparray = numpy.zeros(t, dtype=dtype)
if white is True:
nparray[:, :, (0, 1, 2)] = 255
img = sppasImage(input_array=nparray)
if alpha is not None:
return img.ialpha(alpha)
return img
ired
Return a copy of the image in red-color.
Parameters
- value: (int) Fixed red value ranging (0, 255)
Returns
View Source
def ired(self, value=0):
"""Return a copy of the image in red-color.
:param value: (int) Fixed red value ranging (0, 255)
:return: (sppasImage)
"""
value = int(value)
value = value % 255
img = self.copy()
img[:, :, (0, 1)] = value
return sppasImage(input_array=img)
igreen
Return a copy of the image in green-color.
Parameters
- value: (int) Fixed green value ranging (0, 255)
Returns
View Source
def igreen(self, value=0):
"""Return a copy of the image in green-color.
:param value: (int) Fixed green value ranging (0, 255)
:return: (sppasImage)
"""
value = int(value)
value = value % 255
img_green = self.copy()
img_green[:, :, (0, 2)] = value
return sppasImage(input_array=img_green)
iblue
Return a copy of the image in blue-color.
Parameters
- value: (int) Fixed blue value ranging (0, 255)
Returns
View Source
def iblue(self, value=0):
"""Return a copy of the image in blue-color.
:param value: (int) Fixed blue value ranging (0, 255)
:return: (sppasImage)
"""
value = int(value)
value = value % 255
img = self.copy()
img[:, :, (1, 2)] = value
return sppasImage(input_array=img)
ialpha
Return a copy of the image in RGBA colors.
Do nothing if no channel defined.
Parameters
- value: (int) Alpha value for transparency (0-255)
- direction: (int) 0 means to assign the value to each pixel, but -1 means to only assign the value to pixels if the existing transparency is higher than value (lowers are un-changed) and +1 means to assign alpha value if the existing one is lower (higher values are unchanged).
Returns
View Source
def ialpha(self, value=0, direction=0):
"""Return a copy of the image in RGBA colors.
Do nothing if no channel defined.
:param value: (int) Alpha value for transparency (0-255)
:param direction: (int) 0 means to assign the value to each pixel, but
-1 means to only assign the value to pixels if the existing transparency
is higher than value (lowers are un-changed) and +1 means to assign
alpha value if the existing one is lower (higher values are unchanged).
:return: (sppasImage)
"""
if self.channel == 3:
imga = sppasImage(input_array=cv2.cvtColor(self, cv2.COLOR_RGB2RGBA))
else:
imga = self.copy()
if imga.channel == 4:
value = int(value)
value = value % 255
if direction == 0:
imga[:, :, 3] = value
elif direction < 0:
numpy.clip(imga[:, :, 3], 0, value, out=imga[:, :, 3])
else:
numpy.clip(imga[:, :, 3], value, 255, out=imga[:, :, 3])
return imga
ibgr
Return a copy of the image with given in BGR/BGRA color values.
Parameters
- bgr: (tuple) A tuple(b, g, r) or tuple(b, g, r, a) color.
Returns
View Source
def ibgr(self, bgr):
"""Return a copy of the image with given in BGR/BGRA color values.
:param bgr: (tuple) A tuple(b, g, r) or tuple(b, g, r, a) color.
:return: (sppasImage)
"""
if len(bgr) < 3:
raise ValueError('Expected a (b, g, r) or (b, g, r, a) color. Got {} instead.'.format(bgr))
img = self.copy()
value = int(bgr[0])
value = value % 255
img[:, :, 0] = value
value = int(bgr[1])
value = value % 255
img[:, :, 1] = value
value = int(bgr[2])
value = value % 255
img[:, :, 2] = value
if len(bgr) == 4:
return img.ialpha(bgr[3])
return img
ibgra_to_bgr
Return a copy of the image without the alpha channel.
Returns
View Source
def ibgra_to_bgr(self):
"""Return a copy of the image without the alpha channel.
:return: (sppasImage)
"""
return sppasImage(input_array=cv2.cvtColor(self, cv2.COLOR_BGRA2BGR))
igray
Return a copy of the image in grayscale.
Returns
View Source
def igray(self):
"""Return a copy of the image in grayscale.
:return: (sppasImage)
"""
if self.channel == 4:
avg = numpy.average(self, weights=[0.114, 0.587, 0.2989, 1], axis=2)
elif self.channel == 3:
avg = numpy.average(self, weights=[0.114, 0.587, 0.2989], axis=2)
else:
return self.copy()
gray = self.copy()
gray[:, :, 0] = avg
gray[:, :, 1] = avg
gray[:, :, 2] = avg
return sppasImage(input_array=gray)
inegative
Return a copy of the image in negative/positive colors.
Returns
View Source
def inegative(self):
"""Return a copy of the image in negative/positive colors.
:return: (sppasImage)
"""
img = 255 - self
return sppasImage(input_array=img)
ireduction
Return a copy of the image with a color-reduction applied.
Parameters
- value: (int) Reduction value in range(0, 255)
Returns
View Source
def ireduction(self, value=128):
"""Return a copy of the image with a color-reduction applied.
:param value: (int) Reduction value in range(0, 255)
:return: (sppasImage)
"""
value = int(value)
if value < 0:
return self.copy()
coeff = value % 255
img = self // coeff * coeff
return sppasImage(input_array=img)
igamma
Return a copy of the image with lightness changed.
Parameters
- coeff: (float) Set a value in range (0, 1) to increase lightness, or a value > 1 to increase darkness.
Returns
View Source
def igamma(self, coeff=1.0):
"""Return a copy of the image with lightness changed.
:param coeff: (float) Set a value in range (0, 1) to increase
lightness, or a value > 1 to increase darkness.
:return: (sppasImage)
"""
if coeff < 0.0:
coeff = 0.0
img = 255.0 * (self / 255.0) ** coeff
return sppasImage(input_array=img)
ito_rgb
Return a copy of the image representing RGB colors.
Remove alpha channel if any.
Raises
TypeError
Returns
- (sppasImage) an RGB image
View Source
def ito_rgb(self):
"""Return a copy of the image representing RGB colors.
Remove alpha channel if any.
:raises: TypeError
:return: (sppasImage) an RGB image
"""
img = self.copy()
if self.channel > 2:
return img[:, :, [2, 1, 0]]
raise sppasTypeError('image', 'BGR/BGRA sppasImage')
ishadow
Return a copy of image with a shadow added.
Parameters
- x: (int) Shadow width
- y: (int) Shadow height
Returns
View Source
def ishadow(self, x=5, y=20):
"""Return a copy of image with a shadow added.
:param x: (int) Shadow width
:param y: (int) Shadow height
:return: (sppasImage)
"""
tmp = self.igray()
tmp = tmp.ishift(x, y)
return tmp.ioverlay(self, (0, 0))
icrop
Return a trimmed part of the image at given coordinates.
Parameters
- coord: (sppasCoords) crop to these x, y, w, h values.
Returns
View Source
def icrop(self, coord):
"""Return a trimmed part of the image at given coordinates.
:param coord: (sppasCoords) crop to these x, y, w, h values.
:return: (sppasImage)
"""
coord = sppasCoords.to_coords(coord)
x1 = coord.x
x2 = coord.x + coord.w
y1 = coord.y
y2 = coord.y + coord.h
cropped = self[y1:y2, x1:x2]
return sppasImage(input_array=cropped)
itrim
Return a cropped part of the image.
Parameters
- coord: (tuple or sppasCoords)
Returns
View Source
def itrim(self, coord):
"""Return a cropped part of the image.
:param coord: (tuple or sppasCoords)
:return: (sppasImage)
"""
return self.icrop(coord)
iresize
Return a copy of the image with the specified width and height.
Parameters
- width: (int) The width to resize to (0=proportional to height)
- height: (int) The height to resize to (0=proportional to width)
Returns
View Source
def iresize(self, width=0, height=0):
"""Return a copy of the image with the specified width and height.
:param width: (int) The width to resize to (0=proportional to height)
:param height: (int) The height to resize to (0=proportional to width)
:return: (sppasImage)
"""
if width == 0 and height == 0:
return self.copy()
prop_width, prop_height = self.get_proportional_size(width, height)
if prop_width + prop_height == 0:
return self.copy()
dif = self.height if self.height > self.width else self.width
interpol = cv2.INTER_AREA if dif > (width + height) // 2 else cv2.INTER_CUBIC
image = cv2.resize(self, (prop_width, prop_height), interpolation=interpol)
return sppasImage(input_array=image)
izoom
Return a zoomed copy of the image.
Resize and crop the image to zoom it to the given size.
Keep the original aspect ratio of the image, but crop if necessary.
Parameters
- width: (int) The width to resize to
- height: (int) The height to resize to
Returns
View Source
def izoom(self, width, height):
"""Return a zoomed copy of the image.
Resize and crop the image to zoom it to the given size.
Keep the original aspect ratio of the image, but crop if necessary.
:param width: (int) The width to resize to
:param height: (int) The height to resize to
:return: (sppasImage)
"""
aspect_ratio = int(100.0 * float(self.width) / float(self.height)) / 100.0
res_aspect_ratio = int(100.0 * float(width) / float(height)) / 100.0
if aspect_ratio > res_aspect_ratio:
img_w = int(aspect_ratio * float(height))
img_h = height
img = self.iresize(img_w, img_h)
x1 = int(float(img_w - width) / 2.0)
x2 = x1 + width
img = img[:, x1:x2, :]
elif aspect_ratio < res_aspect_ratio:
img_w = width
img_h = int(float(width) / aspect_ratio)
img = self.iresize(img_w, img_h)
y1 = int(float(img_h - height) / 2.0)
y2 = y1 + height
img = img[y1:y2, :, :]
else:
img = self.iresize(width, height)
return sppasImage(input_array=img)
icenter
Return a copy of the image centered in an image of given size.
Center the image into a blank image of the given size.
Keep the original aspect ratio of the image, crop if necessary or
add a black border all around.
Parameters
- width: (int) The width to resize to
- height: (int) The height to resize to
Returns
View Source
def icenter(self, width, height):
"""Return a copy of the image centered in an image of given size.
Center the image into a blank image of the given size.
Keep the original aspect ratio of the image, crop if necessary or
add a black border all around.
:param width: (int) The width to resize to
:param height: (int) The height to resize to
:return: (sppasImage)
"""
coord = sppasCoords(0, 0, width, height)
if self.width > width:
coord.x = (self.width - width) // 2
if self.height > height:
coord.y = (self.height - height) // 2
img = self.icrop(coord)
if self.channel == 4:
mask = sppasImage(0).blank_image(width, height, white=False, alpha=0)
else:
mask = sppasImage(0).blank_image(width, height)
x_pos = (width - img.width) // 2
y_pos = (height - img.height) // 2
mask[y_pos:y_pos + img.height, x_pos:x_pos + img.width, :] = img[:img.height, :img.width, :]
return sppasImage(input_array=mask)
iextend
Return an extended copy of the image of given size.
Scale the image to match the given size, keeping aspect ratio.
Keep the original aspect ratio of the image, add a black border.
Parameters
- width: (int) The width to resize to
- height: (int) The height to resize to
Returns
View Source
def iextend(self, width, height):
"""Return an extended copy of the image of given size.
Scale the image to match the given size, keeping aspect ratio.
Keep the original aspect ratio of the image, add a black border.
:param width: (int) The width to resize to
:param height: (int) The height to resize to
:return: (sppasImage)
"""
aspect_ratio = int(100.0 * float(self.width) / float(self.height)) / 100.0
res_aspect_ratio = int(100.0 * float(width) / float(height)) / 100.0
if aspect_ratio == res_aspect_ratio:
return self.iresize(width, height)
elif aspect_ratio > res_aspect_ratio:
coeff = float(width) / float(self.width)
img = self.iresize(width, int(coeff * float(self.height)))
else:
coeff = float(height) / float(self.height)
img = self.iresize(int(coeff * float(self.width)), height)
return img.icenter(width, height)
irotate
Return a rotated copy of the image with the given angle.
This method is part of imutils under the terms of the MIT License (MIT)
Copyright (c) 2015-2016 Adrian Rosebrock, http://www.pyimagesearch.com
See here for details:
https://www.pyimagesearch.com/2017/01/02/rotate-images-correctly-with-opencv-and-python/
Parameters
- angle: (float) Rotation angle in degrees.
- center: (int) Center of the rotation in the source image.
- scale: (float) Isotropic scale factor.
- redimension: (bool) Scale the image to fit in the previous square
Returns
View Source
def irotate(self, angle, center=None, scale=1.0, redimension=True):
"""Return a rotated copy of the image with the given angle.
This method is part of imutils under the terms of the MIT License (MIT)
Copyright (c) 2015-2016 Adrian Rosebrock, http://www.pyimagesearch.com
See here for details:
https://www.pyimagesearch.com/2017/01/02/rotate-images-correctly-with-opencv-and-python/
:param angle: (float) Rotation angle in degrees.
:param center: (int) Center of the rotation in the source image.
:param scale: (float) Isotropic scale factor.
:param redimension: (bool) Scale the image to fit in the previous square
:return: (sppasImage)
"""
h, w = self.shape[:2]
if center is None:
center = (w // 2, h // 2)
matrix = cv2.getRotationMatrix2D(center, -angle, scale)
if redimension is True:
cos = numpy.abs(matrix[0, 0])
sin = numpy.abs(matrix[0, 1])
new_width = int(h * sin + w * cos)
new_height = int(h * cos + w * sin)
matrix[0, 2] += new_width // 2 - center[0]
matrix[1, 2] += new_height // 2 - center[1]
else:
new_width = w
new_height = h
rotated = cv2.warpAffine(self, matrix, (new_width, new_height))
return sppasImage(input_array=rotated)
ishift
Return a shifted copy of the image at given coordinates.
Shift the content at left/right and/or top/bottom.
Parameters
Returns
View Source
def ishift(self, x, y):
"""Return a shifted copy of the image at given coordinates.
Shift the content at left/right and/or top/bottom.
:param x: (int)
:param y: (int)
:return: (sppasImage)
"""
h, w = self.shape[:2]
matrix = numpy.float32([[1, 0, x], [0, 1, y]])
shifted = cv2.warpAffine(self, matrix, (w, h))
return sppasImage(input_array=shifted)
iflip
Return a flipped copy of the image.
flipcode = 0: flip vertically
flipcode > 0: flip horizontally
flip_code < 0: flip vertically and horizontally
Parameters
- flip_code: (int) Indicate the way to flip the image
Returns
View Source
def iflip(self, flip_code=-1):
"""Return a flipped copy of the image.
flip_code = 0: flip vertically
flip_code > 0: flip horizontally
flip_code < 0: flip vertically and horizontally
:param flip_code: (int) Indicate the way to flip the image
:return: (sppasImage)
"""
if flip_code == 0:
img = numpy.flipud(self)
elif flip_code > 0:
img = numpy.fliplr(self)
else:
img = numpy.flip(self, (0, 1))
return sppasImage(input_array=img)
imask
Return a copy of the image masked with the other given image.
Parameters
- other: (sppasImage) Image to mask (black areas)
Returns
View Source
def imask(self, other):
"""Return a copy of the image masked with the other given image.
:param other: (sppasImage) Image to mask (black areas)
:return: (sppasImage)
"""
w, h = self.size()
other = other.iresize(w, h)
dst = self * other / 255
dst.astype(numpy.uint8)
return sppasImage(input_array=dst)
iblur
Return a copy of the image with smoothed borders.
Parameters
- value: (int) Kernel value, from 0 to 51.
- method: (str) One of: None, "gaussian" or "median"
Returns
View Source
def iblur(self, value=51, method='gaussian'):
"""Return a copy of the image with smoothed borders.
:param value: (int) Kernel value, from 0 to 51.
:param method: (str) One of: None, "gaussian" or "median"
:return: (sppasImage)
"""
if method is None:
mask_blur = cv2.blur(self, (value, value))
elif method.lower() == 'median':
mask_blur = cv2.medianBlur(self, value)
else:
mask_blur = cv2.GaussianBlur(self, (value, value), cv2.BORDER_DEFAULT)
return sppasImage(input_array=mask_blur)
icontours
Return a blank image with the contours of the image in color.
Parameters
- threshold: (int) value which is used to classify the pixel values (0-255)
- color: (tuple) BGR values of the color to draw the contours
Returns
View Source
def icontours(self, threshold=128, color=(0, 255, 0)):
"""Return a blank image with the contours of the image in color.
:param threshold: (int) value which is used to classify the pixel values (0-255)
:param color: (tuple) BGR values of the color to draw the contours
:return: (sppasImage)
"""
if self.channel < 2:
logging.error('Invalid image to draw a contour.')
return self
img_grey = cv2.cvtColor(self, cv2.COLOR_BGR2GRAY)
_, thresh_img = cv2.threshold(img_grey, threshold, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(thresh_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
img_contours = numpy.zeros(self.shape)
cv2.drawContours(img_contours, contours, -1, color, 3)
return sppasImage(input_array=img_contours)
ipaste
Return a copy of the image with other paste on it at given coords.
Replace the current image with the given one at given coords.
Parameters
- other: (sppasImage) Image to paste
- coord: (sppasCoords) Position and optionally size to paste
Returns
View Source
def ipaste(self, other, coord):
"""Return a copy of the image with other paste on it at given coords.
Replace the current image with the given one at given coords.
:param other: (sppasImage) Image to paste
:param coord: (sppasCoords) Position and optionally size to paste
:return: (sppasImage)
"""
img = self.copy()
other = sppasImage(input_array=other)
coord = sppasCoords.to_coords(coord)
if other.channel != self.channel:
if other.channel == 3 and self.channel == 4:
other = other.ialpha(0)
if other.channel == 4 and self.channel == 3:
img = self.ialpha(0)
if coord.w > 0 and coord.h > 0:
paste_img = other.iresize(coord.w, coord.h)
else:
paste_img = other
w, h = other.size()
coord.w = w
coord.h = h
w, h = self.size()
to_crop = False
if coord.x + coord.w > w:
new_w = w - coord.x
coord.w = new_w
to_crop = True
if coord.y + coord.h > h:
new_h = h - coord.y
to_crop = True
coord.h = new_h
if to_crop is True:
paste_img = paste_img.icrop((0, 0, coord.w, coord.h))
x1 = coord.x
x2 = coord.x + coord.w
y1 = coord.y
y2 = coord.y + coord.h
img[y1:y2, x1:x2] = paste_img
return img
iblend
Return a copy of the image with the other image added or blended.
Parameters
- other: (sppasImage) Image to blend with
- coord: (sppasCoord) Blend only the given area of self with other
- weight1: (float) coeff on the image
- weight2: (float) coeff on the other image
Returns
View Source
def iblend(self, other, coord=None, weight1=0.5, weight2=0.5):
"""Return a copy of the image with the other image added or blended.
:param other: (sppasImage) Image to blend with
:param coord: (sppasCoord) Blend only the given area of self with other
:param weight1: (float) coeff on the image
:param weight2: (float) coeff on the other image
:return: (sppasImage)
"""
w, h = self.size()
img = self.copy()
if coord is None:
other = other.iresize(w, h)
else:
blank = sppasImage(0).blank_image(w, h, white=False, alpha=0)
if other.channel == 3:
other = other.ialpha(254)
other = blank.ipaste(other, coord)
if self.channel == 3:
img = self.ialpha(254)
blended = cv2.addWeighted(img, weight1, other, weight2, 0)
return sppasImage(input_array=blended)
ioverlay
Return a copy of the image with the other image added.
Parameters
- other: (sppasImage) Image to blend with
- coord: (sppasCoord) Overlay in the given area of self with other
Returns
View Source
def ioverlay(self, other, coord):
"""Return a copy of the image with the other image added.
:param other: (sppasImage) Image to blend with
:param coord: (sppasCoord) Overlay in the given area of self with other
:return: (sppasImage)
"""
back_image = self.copy()
w, h = self.size()
over_image = sppasImage(input_array=other)
coord = sppasCoords.to_coords(coord)
if over_image.channel == 3:
over_image = over_image.ialpha(254)
if back_image.channel == 3:
back_image = self.ialpha(254)
if coord.w > 0 and coord.h > 0:
over_image = over_image.iresize(coord.w, coord.h)
cols, rows = over_image.shape[:2]
x = coord.x
y = coord.y
if x + rows > w:
rows = w - x
if y + cols > h:
cols = h - y
tmp = sppasImage(0).blank_image(w, h, white=False, alpha=254)
over_image = tmp.ipaste(over_image, (x, y))
alpha_background = back_image[:, :, 3] / 255.0
alpha_foreground = over_image[:, :, 3] / 255.0
roi_over = back_image.copy()
for color in range(0, 3):
roi_over[:, :, color] = alpha_foreground * over_image[:, :, color] + alpha_background * roi_over[:, :, color] * (1 - alpha_foreground)
roi_over[:, :, 3] = (1 - (1 - alpha_foreground) * (1 - alpha_background)) * 255
if rows > 0 and cols > 0:
black = sppasImage(0).blank_image(rows, cols, white=False, alpha=254)
back_image = back_image.ipaste(black, (x, y))
combined = cv2.add(back_image, roi_over)
return sppasImage(input_array=combined)
isurround
Return a new image with a square surrounding all the given coords.
Parameters
- coords: (List of sppasCoords) Areas to surround
- color: (int, int, int) Rectangle color
- thickness: (int) Thickness of lines that make up the rectangle. Negative values, like CV_FILLED , mean that the function has to draw a filled rectangle.
- score: (bool) Add the confidence score of the coords
Returns
View Source
def isurround(self, coords, color=(50, 100, 200), thickness=2, score=False):
"""Return a new image with a square surrounding all the given coords.
:param coords: (List of sppasCoords) Areas to surround
:param color: (int, int, int) Rectangle color
:param thickness: (int) Thickness of lines that make up the rectangle.
Negative values, like CV_FILLED , mean that the function has to
draw a filled rectangle.
:param score: (bool) Add the confidence score of the coords
:return: (sppasImage)
"""
img = self.copy()
for c in coords:
c = sppasCoords.to_coords(c)
if c.w > 0 and c.h > 0:
text = ''
if score is True and c.get_confidence() > 0.0:
text = '{:.3f}'.format(c.get_confidence())
img.surround_coord(c, color, thickness, text)
else:
img.surround_point(c, color, thickness)
return img
icartoon
Applied a filter on the image to create a cartoon effect.
Parameters
- colorize: (bool) If we want our image in only black and white (False) or with colors (True).
Returns
- (sppasImage) The image with the filter applied on it
View Source
def icartoon(self, colorize=True):
"""Applied a filter on the image to create a cartoon effect.
:param colorize: (bool) If we want our image in only black and
white (False) or with colors (True).
:return: (sppasImage) The image with the filter applied on it
"""
alpha_image = None
if self.channel == 4:
alpha_image = self[:, :, 3] / 255.0
img = self.ibgra_to_bgr()
else:
img = self.copy()
img_blur = cv2.medianBlur(img, 5)
img_bf = cv2.bilateralFilter(img_blur, d=3, sigmaColor=50, sigmaSpace=50)
img_lp_al = cv2.Laplacian(img_bf, cv2.CV_8U, ksize=5)
img_lp_al_grey = cv2.cvtColor(img_lp_al, cv2.COLOR_BGR2GRAY)
blur_al = cv2.GaussianBlur(img_lp_al_grey, (5, 5), 0)
_, tresh_al = cv2.threshold(blur_al, 245, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
inverted_bilateral = cv2.subtract(255, tresh_al)
if colorize is True:
img_color = cv2.bilateralFilter(img, d=8, sigmaColor=250, sigmaSpace=250)
img_color = sppasImage(input_array=cv2.bitwise_and(img_color, img_color, mask=inverted_bilateral))
if alpha_image is not None:
img_color = img_color.ialpha(254)
img_color[:, :, 3] = alpha_image * 255
return img_color
if alpha_image is not None:
img = sppasImage(input_array=inverted_bilateral).ialpha(254)
img[:, :, 3] = alpha_image * 255
return img
else:
return sppasImage(input_array=inverted_bilateral)
iquantization_color
Smooth colors, down-sample and Up-sample the original image colors.
Parameters
- nbdownsamp: (int) number of downscaling steps
Returns
- (sppasImage) The image with the filter applied on it
View Source
def iquantization_color(self, nb_down_samp=2):
"""Smooth colors, down-sample and Up-sample the original image colors.
:param nb_down_samp: (int) number of downscaling steps
:return: (sppasImage) The image with the filter applied on it
"""
img_color = self.copy()
for _ in range(nb_down_samp):
img_color = cv2.pyrDown(img_color)
for _ in range(50):
img_color = cv2.bilateralFilter(img_color, 9, 9, 7)
for _ in range(nb_down_samp):
img_color = cv2.pyrUp(img_color)
return sppasImage(input_array=img_color)
iinvert
Applied an invert filter on the image.
Returns
- (sppasImage) The image with the filter applied on it
View Source
def iinvert(self):
"""Applied an invert filter on the image.
:return: (sppasImage) The image with the filter applied on it
"""
"\n alpha_image = None\n\n # image doesn't have an alpha channel\n if self.channel == 3:\n img = self.copy()\n else:\n # normalize alpha channels from 0-255 to 0-1\n alpha_image = self[:, :, 3] / 255.0\n # get the image without the alpha channel\n img = self.ibgra_to_bgr()\n\n # apply the invert filter\n invert_array = cv2.bitwise_not(img)\n\n if alpha_image is not None:\n # create alpha channel and restore original image alpha\n img = sppasImage(input_array=invert_array).ialpha(254)\n img[:, :, 3] = alpha_image * 255\n\n return img\n "
invert_array = cv2.bitwise_not(self.copy())
return sppasImage(input_array=invert_array)
ioverlay_color
Applied an overlay with a specified color on the image.
Parameters
- color_overlay: (tuple[int, int, int]) The color of the overlay on the rgb format
- intensity: (float) The intensity
Returns
- (sppasImage) The image with the filter applied on it
View Source
def ioverlay_color(self, color_overlay, intensity=0.2):
"""Applied an overlay with a specified color on the image.
:param color_overlay: (tuple[int, int, int]) The color of the overlay on the rgb format
:param intensity: (float) The intensity
:return: (sppasImage) The image with the filter applied on it
"""
image = cv2.cvtColor(self.copy(), cv2.COLOR_BGR2BGRA)
image_height, image_width, _ = image.shape
color_bgra = color_overlay[::-1] + (1,)
overlay = numpy.full((image_height, image_width, 4), color_bgra, dtype='uint8')
cv2.addWeighted(overlay, intensity, image, 1.0, 0, image)
image = cv2.cvtColor(image, cv2.COLOR_BGRA2BGR)
return sppasImage(input_array=image)
iuint8
Return a copy of the image with dtype=numpy.uint8.
View Source
def iuint8(self):
"""Return a copy of the image with dtype=numpy.uint8."""
img = self / self.max()
img = 255 * img
return img.astype(numpy.uint8)
write
Write the image on disk.
Parameters
- filename: (str) Name of the image file
Raises
(ImageWriteError)
View Source
def write(self, filename):
"""Write the image on disk.
:param filename: (str) Name of the image file
:raises: (ImageWriteError)
"""
try:
cv2.imwrite(filename, self)
except cv2.error as e:
logging.error('Error when writing file {}: {}'.format(filename, str(e)))
raise ImageWriteError(filename)