I'm a programming beginner (a hobbyist, non-engineer). It is created while studying. I referred to the following page. Thank you very much.
https://postd.cc/image-processing-101/
Windows10 Python 3.8 OpenCV 4.0.1 notebook
I make Digimon apps as a hobby. (↓ like this)
Digimon to be incorporated into the app is Digimon Pendulum Z
The ** dot picture making ** part of these 3 became very troublesome.
Because the actual Digimon itself is drawn in 16x16. Even if you draw it as it is, it will be blurred if you stretch it (Left: Agumon of the actual machine Right: Agumon drawn with 32 x 32)
Besides, I want to express the line between the dots of the actual machine **, so I drew it as 1 dot 7px (1px between dots) with 8x 128x128.
This ~~ due to useless commitment ~~ Dot striking became very troublesome. I wondered if I could make a pixel art from a photo **.
In the flow Original image → Threshold value binarization → Regeneration Start thinking about that. (Mostly just trace the pages that I referred to)
This time I prepared Apocalymon (apocaly_0.jpg). It has been trimmed in the area of 16x16 that you want to create.
#Various imports
import cv2, matplotlib
import numpy as np
import matplotlib.pyplot as plt
#Loading images
img = cv2.imread('images/apocaly_0.jpg')
#Grayscale
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
#Binarized at threshold 128
_, threshold_img = cv2.threshold(gray_img, 128, 255, cv2.THRESH_BINARY)
#Display image by returning grayscale to RGB
threshold_img = cv2.cvtColor(threshold_img, cv2.COLOR_GRAY2RGB)
plt.imshow(threshold_img)
It was nicely divided into black and white. I tried some threshold adjustments and settled on 128.
#16 divisions of height and width of the image itself
h, w, _ = img.shape
cell_width = w/16
cell_height = h/16
#Make the delimiter position an array
col_cell = list(range(17))
row_cell = list(range(17))
for i in range(17):
col_cell[i] = round(cellWidth * col_cell[i])
row_cell[i] = round(cellHeight * row_cell[i])
I created an array of delimiters as.
print(col_cell)
#result[0, 26, 53, 79, 106, 132, 159, 185, 212, 238, 264, 291, 317, 344, 370, 397, 423]
print(row_cell)
#result[0, 28, 56, 84, 112, 139, 167, 195, 223, 251, 279, 307, 334, 362, 390, 418, 446]
Now that we have a grid of 16x16 area, we can finally calculate.
# [line i,jth column]Element acquisition of
for i in range(16):
for j in range(16):
#Cut out as area cell
cell = threshold_img[row_cell[i]:row_cell[i+1]-1, col_cell[j]:col_cell[j+1]-1]
#Row average in cell
ave_per_row = np.average(cell,axis=0)
#Row average average=Overall average
ave_color = np.average(ave_per_row, axis=0)
ave_value = np.average(ave_color)
#Stored as white → 0 black → 1
if ave_value >= 220:
dot[i][j] = 0
else:
dot[i][j] = 1
If the average value ave_value
is close to 255, white → 0
is substituted, otherwise it is close to black, so 1
is substituted.
print(dot)
#result
[[0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1],
[0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0],
[1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1],
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0],
[0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
I was able to express Apocalymon safely with 01. I thought it was very Digimon-like here.
Finally regenerated
#Create a 128 x 128 area
width = 128
height = 128
dot_img = np.zeros((height,width,3), dtype=np.uint8)
for i in range(16):
for j in range(16):
if dot[i][j] == 0:
#White → 255
dot_img[i*8:i*8+8,j*8:j*8+8] = 255
else:
#Black → 0
dot_img[i*8:i*8+8,j*8:j*8+8] = 0
plt.imshow(dot_img)
I was able to do it safely!
The 1px line between the dots and the white part are transparent and made into png, etc. Although it is still in the middle, the goal is achieved for the time being.
Thank you for reading this far.
I'm writing this article
I made white → 0 black → 1 on the way, but I thought it would be smarter to make it white → 1 black → 0 and make it dot [i] [j] * 255
when regenerating.
It's important to look back.
Recommended Posts