Motive As you know, Irasutoya continues to release trendy free materials. Suddenly I was wondering what would happen if these images were made into pixel art, so I created it.
Method As I wrote in Wizard's Forest, it is said that the NES display color scheme is about 52. (Not deterministic.) Here, in order to make it look like a NES, I will try to reduce the color scheme of each of R, G, B into 4 parts and display it.
Each range is 0 to 255
, but if you simply divide it, you get[0, 85, 170, 255]
.
All color combinations have a 64
pattern, but when you actually output it as an image, it will be displayed as follows.
import cv2
import numpy as np
if __name__ == "__main__":
height = 576
width = 1024
range_color = [0, 85, 170, 255]
mono = np.zeros((height, width, 3), np.uint8)
mono[:] = tuple((0,0,0))
for r in range(4):
for g in range(4):
for b in range(4):
mono[144*b:144*(b+1), 64*(r+g*4):64*(r+(g*4+1))] = tuple((85*b,85*g,85*r))
cv2.imwrite("out.png ", mono)
As an aside, I thought that there was no gray color at first glance, but it is displayed in 2 rows and 6 columns (85,85,85)
and 3 rows and 11 columns(170,170,170)
, respectively.
So, how to judge by the number of the original color data, but as an example, if you want to distribute the value of 110
, judge which is closer to 85 ~ 170
. Since 85
is the closest here, convert it to 110-> 85
and apply this algorithm to all pixels.
Develop
import cv2
import numpy as np
import sys
def resize(src):
h,w = mat.shape[:-1]
height = (h // 16) * 16
width = (w // 16)* 16
return cv2.resize(mat,(width,height))
def convertReduceColor(src):
thresholds = [42,127,212]
range_color = [0, 85, 170, 255]
count = 0
for th in thresholds:
if src <= th:
break
count += 1
return range_color[count]
if __name__ == "__main__":
__CELL_SIZE__ = 4
path = sys.argv[1]
mat = cv2.imread(path,cv2.IMREAD_UNCHANGED)
mat = resize(mat)
height, width = mat.shape[:-1]
for w in range(width//__CELL_SIZE__-1):
for h in range(height//__CELL_SIZE__-1):
c = np.mean(
np.mean(
mat[h*__CELL_SIZE__:(h+1)*__CELL_SIZE__,
w*__CELL_SIZE__:(w+1)*__CELL_SIZE__], axis=0
),
axis=0
)
mat[
h*__CELL_SIZE__:(h+1)*__CELL_SIZE__,
w*__CELL_SIZE__:(w+1)*__CELL_SIZE__
] = tuple([convertReduceColor(c[0]), convertReduceColor(c[1]), convertReduceColor(c[2]), c[3]])
cv2.imwrite("output.png ",mat)
np.mean(np.mean(mat[h*__CELL_SIZE__:(h+1)*__CELL_SIZE__, w*__CELL_SIZE__:(w+1)*__CELL_SIZE__], axis=0),axis=0)
Here, the average value of pixels is obtained from the cell size.
In addition, convertReduceColor
is used to make an approximation judgment for each of RGB.
Result
Source image | Pixel size | After treatment |
---|---|---|
4 | ||
8 | ||
16 | ||
4 | ||
8 | ||
16 | ||
4 | ||
8 | ||
16 |
――The most successful image is a cat with a cell size of 16. The right end has not been processed, but I think that it is a dot picture like that as a whole. If you want to make the right edge dot-like, you have to reconsider the resizing process. ――When converting to a pixel art, it is easier to succeed if there is one person / object in one illustration. ――Basically, it is an image of Irasutoya, but the feature is that the section is filled with uneven felt tone. Therefore, it looks like an object is not filled with a single color and contains noise. --The eyes of the penguins image with the cell size set to 4 are (´ ・ ω ・ `). Please note that the character of Irasutoya basically has eyes as dots and is small, so it disappears when the cell size is increased.
Future ――Since I'm worried about noise, it seems quite so with irregular binarization and morphology conversion. ――The actual NES color is different from the color scheme used this time, so it seems better to embed about 50 color schemes to be used with fixed values and match them by neighborhood search.
Reference -Irasutoya -About the NES screen-Wizard's Forest
Recommended Posts