"""
Handy CV2
=========
"""
import cv2 as _cv2
import numpy as np
from PIL import ImageFont, ImageDraw, Image
[docs]def putText(image: np.ndarray, text: str,
org=(0, 0),
font=_cv2.FONT_HERSHEY_PLAIN,
fontScale=1, color=(0, 0, 255),
thickness=1,
lineType=_cv2.LINE_AA,
bottomLeftOrigin=False) -> np.ndarray:
"""Add text to `cv2` image, with default values.
:param image: image array
:param text: text to be added
:param org: origin of text, from top left by default
:param font: font choice
:param fontScale: font size
:param color: BGR color, red by default
:param thickness: font thickness
:param lineType: line type of text
:param bottomLeftOrigin: True to start from bottom left, default False
:return: image with text added
"""
return _cv2.putText(image, text, org, font, fontScale, color, thickness, lineType, bottomLeftOrigin)
[docs]def putChineseText(image: np.ndarray, text: str,
org=(0, 0),
font=None,
fontScale=1, color=(0, 0, 255),
thickness=1,
lineType=None,
bottomLeftOrigin=False) -> np.ndarray:
"""Add CJK text to image
:param image: image array
:param text: text to be added
:param org: origin of text, from top left by default
:param font: font name if in the system, or font file path
:param fontScale: font size. Size 1 corresponds to 12 pixel.
:param color: BGR color, default red.
:param thickness: no effect, place holder.
:param lineType: no effect, place holder.
:param bottomLeftOrigin: True to start from bottom left, default False
:return: image with text added
"""
grey_flag = len(image.shape) == 2
if grey_flag:
image = _cv2.cvtColor(image, _cv2.COLOR_GRAY2BGR)
if bottomLeftOrigin:
org = list(org)
org[1] = image.shape[1] - org[1]
fontScale = int(fontScale * 12)
if thickness != 1:
print("Use fontScale to control thickness.")
if lineType is not None:
print("Use font to control style.")
try:
if font is None:
try:
import importlib.resources as pkg_resources
except ImportError:
# Try backported to PY<37 `importlib_resources`.
import importlib_resources as pkg_resources
from . import resources
with pkg_resources.path(resources, 'NotoSansCJK-Bold.ttc') as p:
font = ImageFont.truetype(str(p), fontScale)
else:
font = ImageFont.truetype(font, fontScale)
except OSError:
print("Download missing font %s" % font)
raise
img_PIL = Image.fromarray(image)
draw = ImageDraw.Draw(img_PIL)
draw.text(org, text, font=font, fill=color[::-1], )
image = np.asarray(img_PIL)
if grey_flag:
image = _cv2.cvtColor(image, _cv2.COLOR_BGR2GRAY)
return image
[docs]def imread(*args, **kwargs) -> np.ndarray:
"""Fail-safe image read
:param args: Pass to :code:`cv2.imread()`. `filename` is required.
:param kwargs: Pass to :code:`cv2.imread()`.
:return: image numpy array
"""
img = _cv2.imread(*args, **kwargs)
if img is None:
raise FileNotFoundError(args[0])
return img
[docs]def imwrite(*args, **kwargs) -> int:
"""Fail-safe and convenient image write. Put image and image filename in any order.
:param args: Pass to :code:`cv2.imwrite()`. `filename` and `img` are required as arguments (order-free) or keywords.
:param kwargs: Pass to :code:`cv2.imwrite()`.
:return: 0,1
:raise: RuntimeError
"""
if 'filename' not in kwargs and 'img' not in kwargs:
if isinstance(args[1], str):
args = [i for i in args]
args[0], args[1] = args[1], args[0]
flag = _cv2.imwrite(*args, **kwargs)
if flag == 0:
raise RuntimeError("Fail to write to %s" % args[0])
return flag
# TODO: ratio-based resize functions