If you make a cheat sheet, you will understand it in the process. This is an article for myself. I intended to write an article specializing in OpenCV, but for some reason I had to write about PIL as well. Some arguments are omitted.
OpenCV
Since the image data of OpenCV is a numpy array, you can create a monochrome image with np.full (). In the case of a black background, it is possible to write a little simpler, but it is not enough to remember individually, so it is omitted.
-* Shape * The shape of the array. If you want to make an RGB image, (height, width, 3)
.
-* Fill_value * The value to fill. If you want to make an RGB image, (b, g, r)
.
-* Dtype * Data type. If you want to make an image, you need to specify dtype = numpy.uint8
.
The following function processes the specified image. What does that mean?
img = cv2.line(img, ...)
And the return value does not have to be reassigned to itself
cv2.line(img, ...)
The value of ʻimg changes just by writing. If you don't want that to happen, you need to copy the original image as a separate object. This is why I set ʻimg_rect = img_origin.copy ()
in this article.
-* img * Image.
-* pt1 , * pt2 * Specify the coordinates of the two points with (x, y)
. integer. It is possible outside the image.
- Color * Line color.
-* Thickness * Line thickness. Optional and default value is 1.
-* img * Image.
-* Pt1 , * pt2 * Diagonal coordinates. Specify with (x, y)
. integer. It is possible outside the image.
- Color * Line color.
-* Thickness * Line thickness. Optional and default value is 1. If -1 is specified, it will be filled.
Use cv2.ellipse () to draw an arc.
-* img * Image.
-* Center * Center coordinates. Specify with (x, y)
. integer.
-* Radius * Radius. integer.
-* Color * Line color.
-* Thickness * Line thickness. Optional and default value is 1. If -1 is specified, it will be filled.
-* img * Image.
-* Center * Center coordinates. Specify with (x, y)
. integer.
-* axes * The major and minor diameters are represented by (a, b)
. Which is vertical and which is horizontal depends on * angle .
- Angle * The rotation angle of the ellipse. The unit is degrees. If ʻangle = 0` and a> b, then it is a horizontally long ellipse.
-* startAngle * The start angle of the arc. The unit is degrees. The standard is not horizontal but * angle * value.
-* EndAngle * The end angle of the arc. You need to specify 0 and 360 when drawing a closed circle or a normal ellipse. It's a hassle.
-* Thickness * Line thickness. Optional and default value is 1. If -1 is specified, it will be filled.
The angle can be a decimal. Also, the direction of rotation from the x-axis to the y-axis is positive. In mathematical xy coordinates, it is counterclockwise, but in the computer coordinate system, the y-axis points downward, so counterclockwise is positive. In other words, this kind of thing.
Well, even if I write so far, I will not use it anyway.
-* img * Image.
-* Pts * Polygonal ** array . A list of numpy arrays. The individual polygons are np.array ([(x1, y1), (x2, y2), ...])
, and they are enclosed in brackets to make a list. Even when drawing one polygon, it is a list with one element.
- isClosed * Specify True
to make a closed polygon by connecting the first point and the last point, and specify False
to make a polygonal line.
- Color * Line color.
-* Thickness * Line thickness. Optional and default value is 1. It cannot be filled by specifying -1.
Writing * pts * is complicated, but you need to master it in order to play with contour detection, so let's do our best to remember it. In the sample program below, a self-made function is incorporated to draw the same figure multiple times. Did you get arrested by the PEP police if you used the space to align them?
polylines_test.py
import numpy as np
import cv2
###Function to offset the coordinates
# [(x1,y1), (x2,y2)]When(a,b)From[(x1+a,y1+b), (x2+a, y2+b)]make
def position_offset(pos, offset):
np_newpos = np.array(pos) + np.array(offset)
list_newpos = list(map(tuple, np_newpos.tolist()))
return list_newpos
###Create a base monochromatic image
imgCV = np.full((180,200,3), (128,128,128), dtype = np.uint8)
###Make 3 same polygonal lines
pos = [(10,10), (80,60), (80,10), (60,30)]
offset1 = ( 0, 0)
offset2 = (100, 40)
offset3 = (100,100)
pts1 = np.array(position_offset(pos, offset1))
pts2 = np.array(position_offset(pos, offset2))
pts3 = np.array(position_offset(pos, offset3))
###Draw a polygon
#Draw one polygon
cv2.polylines(imgCV, [pts1] , True, (255,0,0), 3)
#Draw multiple polygons at once
cv2.polylines(imgCV, [pts2, pts3], True, (0,0,255), 3)
cv2.imshow("polylines", imgCV)
cv2.waitKey(0)
cv2.destroyAllWindows()
The result is this.
Accurately fill polygons with recesses. Wikipedia has an item called Concave Rectangle In the children's encyclopedia I read a long time ago, it was called "Arrow's Root".
If you know that it is a convex polygon, it is faster to use this. If you use this with a concave polygon, it will not cause an error, but it will leave unpainted areas.
-* Points * Coordinate group. Unlike pts, only one polygon can be specified in the numpy array. Why is this guy so different?
-* img * Image.
-* Text * Text. ** Japanese is not available . It is not possible to start a new line with a line feed code.
- org * Specify the ** coordinates at the bottom left of the text with (x, y)
.
- FontFace * font. Not everything. Details will be described later.
-* FontScale * Font size. Essential for troublesome things. The size of "1" depends on the font.
-* Color * Text color.
-* Thickness * Line thickness. Optional and default value is 1.
The following 8 types can be used. HERSHEY is not chocolate, but a vector font developed by Dr. Hershey.
Italics can be created by combining this with cv2.FONT_ITALIC (adding it because it is a built-in constant).
Use this function when you want to place the text in the center of the shape.
There are two outputs. The size of the text represented by (width, height)
and the y coordinate of the baseline as seen from the lowest point of the string. The latter is the one that pops out below such as "y" and "p".
putText_test.py
import numpy as np
import cv2
fonts=[cv2.FONT_HERSHEY_SIMPLEX,
cv2.FONT_HERSHEY_PLAIN,
cv2.FONT_HERSHEY_DUPLEX,
cv2.FONT_HERSHEY_COMPLEX,
cv2.FONT_HERSHEY_TRIPLEX,
cv2.FONT_HERSHEY_COMPLEX_SMALL,
cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
cv2.FONT_HERSHEY_SCRIPT_COMPLEX]
#Create a base monochromatic image
img = np.full((360,600,3), (255,255,255), dtype = np.uint8)
for i, font in enumerate(fonts):
for j in range(2):
for k in range(2):
x, y = 200*(j+1)*k+10, i*40+50
fnt = font if j == 0 else font + cv2.FONT_ITALIC
text = "sample_{}".format(fnt)
cv2.putText(img,
text = text,
org = (x, y),
fontFace = fnt,
fontScale = 1,
color = (0, 0, 255*j),
thickness=1)
#Baseline unused
(w, h), _ = cv2.getTextSize(text = text,
fontFace = fnt,
fontScale = 1,
thickness = 1)
cv2.rectangle(img, (x, y), (x+w, y-h), (255, 0, 0))
cv2.circle(img, (x, y), 3, (255, 0, 0))
cv2.imshow("hershey fonts",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
The center column is a normal font and the right column is an italic font. The left is a composite of the two. There are some fonts that don't have italic effects.
PIL
-* Mode * Mode. " RGB "
, " RGBA "
, " L "
(8-bit grayscale), etc.
-* Size * Size. Specify (width, height)
.
-* Color * Color. If mode =" RGB "
, specify with (r, g, b)
. Not required, default value is black.
To draw a figure on an image, create an ImageDraw.Draw object instead of the Image itself, and draw on it.
-* Xy * Coordinate group. 3 points or more is possible. Write [(x1, y1), (x2, y2), ...]
or [x1, y1, x2, y2, ...]
in the list.
-* Fill * Line color. The default value when in color is white. The default value at grayscale is black.
-* Width * Line width. integer.
-* Joint * The default value is None
. If " curve "
is specified, the connecting part of the polygonal line will be rounded.
Probably a bug, but when using joint =" curve "
, the description of the coordinate group must bexy = [(x1, y1), (x2, y2), ...]
. If xy = [x1, y1, x2, y2, ...]
, an error will occur. Also, if you draw a polygonal line with the default color without setting * fill *, the curve processing will be halfway.
-* xy * Specify 2 points. Write [(x0, y0), (x1, y1)]
or [x0, y0, x1, y1]
in the list.
-* Fill * Fill color. The default value is None (no fill).
-* Outline * Line color.
-* Width * Line width.
-* xy * ** Specify two surrounding points instead of the center. ** Write [(x0, y0), (x1, y1)]
or [x0, y0, x1, y1]
in the list. An image of a circle (ellipse) inscribed in a quadrangle. At this time, x0 <= x1 and y0 <= y1 must be satisfied.
-* Fill * Fill color.
-* Outline * Line color.
-* Width * Line width.
I was wondering why it had such specifications, but when I thought about it, there were many drawing software with such specifications.
If you know the line and rectangle, you can master it. At the moment, the line width cannot be specified and is fixed at 1.
-* Xy * Coordinate group. The first point and the last point are automatically connected. -* Fill * Fill color. -* Outline * Line color.
PIL.ImageDraw.ImageDraw.point (* xy *, * fill ) to make (plural) points ImageDraw.arc ( xy *, * start *, * end *, * fill *, * width ) ImageDraw.chord ( xy *, * start *, * end *, * fill *, * outline *, * width ) to create an arc + string ImageDraw.pieslice ( xy *, * start *, * end *, * fill *, * outline *, * width *) can be used to draw a fan shape (arc + radius). The unit of the angle is degrees, and it increases clockwise from 3 o'clock like cv2.ellipse () of OpenCV.
The method for drawing PIL characters uses the font in the PC, so Japanese can also be used.
-* xy * Specify the coordinates of ** upper left ** of the text with (x, y)
.
-* Text * Text. Line breaks using \ n
are also OK.
-* Fill * Text color.
-* Font * Font. Details will be described later. It can be omitted, and in that case it will be a very small font that cannot be Japanese.
--There are settings such as the amount of line breaks when drawing multiple lines, but they are omitted.
-* Font * Truetype font file name. It will automatically search for the appropriate location, such as C: \ Windows \ Fonts for Windows and / usr / share / fonts for Raspberry Pi. -* Size * Font size. The default value is 10 points. --There are settings such as encoding (default value is Unicode), but they are omitted.
Unlike cv2.getTextSize (), the output is only (width, height)
.
It has become a lot of things. Here, too, the self-made function position_offset () is used.
PIL_test.py
import numpy as np
from PIL import Image, ImageDraw, ImageFont
###Function to offset the coordinates
# [(x1,y1), (x2,y2)]When(a,b)From[(x1+a,y1+b), (x2+a, y2+b)]make
def position_offset(pos, offset):
np_newpos = np.array(pos) + np.array(offset)
list_newpos = list(map(tuple, np_newpos.tolist()))
return list_newpos
###Create a base monochromatic image
imgPIL = Image.new("RGB", (640,480), (128,128,128))
###Create a Draw object
draw = ImageDraw.Draw(imgPIL)
###Line
pos = [(10,10), (80,60), (80,10), (60,30)]
### line
for i in range(6):
# y=0 : joint =Line chart when None is set, and fill is omitted.
draw.line(xy = position_offset(pos,(100*i,0)),
width = i*5,
joint = None)
# y=100 : joint = "curve"Line when
draw.line(xy = position_offset(pos,(100*i,100)),
fill = (0,255,255),
width = i*5,
joint = "curve")
# y=Right end of 200:joint without specifying fill= "curve"Behavior when
#It doesn't have to be inside a for loop, but I've put it here for ease of comparison.
draw.line(xy = position_offset(pos,(100*5,200)),
width = 25,
joint = "curve")
###Even if the same coordinate group as polygon line is used, it becomes a closed polygon.
#Specify fill
draw.polygon(xy = position_offset(pos,(0,200)),
fill = (255,0,0))
#Specify outline
draw.polygon(xy = position_offset(pos,(100,200)),
outline = (0,255,0))
#Specify fill and outline
draw.polygon(xy = position_offset(pos,(200,200)),
fill = (255,0,0),
outline = (0,255,0))
###rectangle and ellipse
pos=[(10,0), (200,70)] #Let's change the order of the two points
for i in range(3):
draw.rectangle(xy = position_offset(pos,(200*i,300)),
fill = None,
outline = (0,0,255),
width = i*5) #width can be 0 even if it is 0
draw.ellipse(xy = position_offset(pos,(200*i,300)),
fill = (255,255,0),
outline = (0,255,0),
width = i*5)
###arc, chord and pieslice
start, end = 45, 300
#arc arc outline is abbreviated
draw.arc(xy = position_offset(pos,(0,400)),
start = start,
end = end,
width = 4)
#chord string
draw.chord(xy = position_offset(pos,(200,400)),
start = start,
end = end,
fill = (255,0,0),
outline = (0,255,0))
#pieslice fan
draw.pieslice(xy = position_offset(pos,(400,400)),
start = start,
end = end,
fill = (255,0,0),
outline = (0,255,0))
###Draw letters
#Draw letters with minimal settings
draw.text(xy = (520,190),
text = "bug? -> ")
#Draw characters in the specified font
#The font was DF Reiga Song
font = ImageFont.truetype(font="Dflgs9.TTC",
size=30)
draw.text(xy = (440,250),
text = "bug? →",
fill = (0,0,0),
font = font)
###Display image
imgPIL.show()
The result is this.
Thank you to teratail for creating my own function position_offset (). Thank you very much. https://teratail.com/questions/234513
I want to display Japanese in OpenCV. For that purpose, PIL should be used only for that part. There are many such articles on the web, but I'm not happy with them. I'm not going to dismiss my predecessors, but I want to create a more practical function.
Recommended Posts