Browse Source

pixel art blog post

pull/101/head
jrtechs 3 years ago
parent
commit
8178180f20
9 changed files with 178 additions and 0 deletions
  1. BIN
      blogContent/headerImages/8-bit.png
  2. +178
    -0
      blogContent/posts/data-science/creating-pixel-art-with-open-cv.md
  3. BIN
      blogContent/posts/data-science/media/pixel/output_10_0.png
  4. BIN
      blogContent/posts/data-science/media/pixel/output_11_0.png
  5. BIN
      blogContent/posts/data-science/media/pixel/output_2_0.png
  6. BIN
      blogContent/posts/data-science/media/pixel/output_3_0.png
  7. BIN
      blogContent/posts/data-science/media/pixel/output_4_0.png
  8. BIN
      blogContent/posts/data-science/media/pixel/output_5_0.png
  9. BIN
      blogContent/posts/data-science/media/pixel/output_9_0.png

BIN
blogContent/headerImages/8-bit.png View File

Before After
Width: 1044  |  Height: 327  |  Size: 196 KiB

+ 178
- 0
blogContent/posts/data-science/creating-pixel-art-with-open-cv.md View File

@ -0,0 +1,178 @@
Let's jump right into the fun and start making pixel art with Open CV.
Before you read this article, consider checkout out these articles:
- [Shallow Dive into Open CV](https://jrtechs.net/open-source/shallow-dive-into-open-cv)
- [Image Clustering with K-means](https://jrtechs.net/data-science/image-clustering-with-k-means)
Like most CV projects, we need to start by importing some libraries and loading an image.
```python
# Open cv library
import cv2
# matplotlib for displaying the images
from matplotlib import pyplot as plt
img = cv2.imread('dolphin.jpg')
```
I like to define scripts to print images nicely in a Jupyter notebook.
```python
def printI(img):
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(rgb)
def printI2(i1, i2):
fig = plt.figure()
ax1 = fig.add_subplot(1,2,1)
ax1.imshow(cv2.cvtColor(i1, cv2.COLOR_BGR2RGB))
ax2 = fig.add_subplot(1,2,2)
ax2.imshow(cv2.cvtColor(i2, cv2.COLOR_BGR2RGB))
printI(img)
```
![original image](media/pixel/output_2_0.png)
To pixelate an image, we can use the open cv resize function.
To make the image viewable, after we shrink the picture, we resize it again to be the size of the original image.
```python
def pixelate(img, w, h):
height, width = img.shape[:2]
# Resize input to "pixelated" size
temp = cv2.resize(img, (w, h), interpolation=cv2.INTER_LINEAR)
# Initialize output image
return cv2.resize(temp, (width, height), interpolation=cv2.INTER_NEAREST)
img16 = pixelate(img, 16, 16)
printI2(img, img16)
```
![pixelated 16x16](media/pixel/output_3_0.png)
We can try a few different shrinkage sizes.
32x32 seems to work the best.
```python
img32 = pixelate(img, 32, 32)
img64 = pixelate(img, 64, 64)
printI2(img32, img64)
```
![pixelated 32x42, 64x64](media/pixel/output_4_0.png)
```python
img8 = pixelate(img, 8, 8)
printI(img8)
```
![original image 8x8 pixelated](media/pixel/output_5_0.png)
Despite the images being pixelated, they have imperfections that normal pixel art wouldn't have.
To remove the noise and make it look smoother, we will do k-means clustering on the pixelated images.
K-means will reduce the number of colors in the image and eliminate any noise.
Most of the clustering code is from my blog post: [Image Clustering with K-means](https://jrtechs.net/data-science/image-clustering-with-k-means)
```python
import skimage
from sklearn.cluster import KMeans
from numpy import linalg as LA
import numpy as np
def colorClustering(idx, img, k):
clusterValues = []
for _ in range(0, k):
clusterValues.append([])
for r in range(0, idx.shape[0]):
for c in range(0, idx.shape[1]):
clusterValues[idx[r][c]].append(img[r][c])
imgC = np.copy(img)
clusterAverages = []
for i in range(0, k):
clusterAverages.append(np.average(clusterValues[i], axis=0))
for r in range(0, idx.shape[0]):
for c in range(0, idx.shape[1]):
imgC[r][c] = clusterAverages[idx[r][c]]
return imgC
```
```python
def segmentImgClrRGB(img, k):
imgC = np.copy(img)
h = img.shape[0]
w = img.shape[1]
imgC.shape = (img.shape[0] * img.shape[1], 3)
#5. Run k-means on the vectorized responses X to get a vector of labels (the clusters);
#
kmeans = KMeans(n_clusters=k, random_state=0).fit(imgC).labels_
#6. Reshape the label results of k-means so that it has the same size as the input image
# Return the label image which we call idx
kmeans.shape = (h, w)
return kmeans
```
```python
def kMeansImage(image, k):
idx = segmentImgClrRGB(image, k)
return colorClustering(idx, image, k)
printI(kMeansImage(img, 5))
```
![original image with k means of 5](media/pixel/output_9_0.png)
Running the k-means algorithm on the 32x32 bit image produces a cool look.
```python
printI(kMeansImage(img32, 3))
```
![32 bit k-means of 3 clusters](media/pixel/output_10_0.png)
We can compare the original, pixelated, and clustered images side by side.
```python
def printI3(i1, i2, i3):
fig = plt.figure(figsize=(18,6))
ax1 = fig.add_subplot(1,3,1)
ax1.imshow(cv2.cvtColor(i1, cv2.COLOR_BGR2RGB))
ax2 = fig.add_subplot(1,3,2)
ax2.imshow(cv2.cvtColor(i2, cv2.COLOR_BGR2RGB))
ax3 = fig.add_subplot(1,3,3)
ax3.imshow(cv2.cvtColor(i3, cv2.COLOR_BGR2RGB))
plt.savefig('trifecta.png')
printI3(img, img32, kMeansImage(img32, 3))
```
![original, pixelated, k-means](media/pixel/output_11_0.png)

BIN
blogContent/posts/data-science/media/pixel/output_10_0.png View File

Before After
Width: 260  |  Height: 252  |  Size: 6.7 KiB

BIN
blogContent/posts/data-science/media/pixel/output_11_0.png View File

Before After
Width: 1044  |  Height: 327  |  Size: 196 KiB

BIN
blogContent/posts/data-science/media/pixel/output_2_0.png View File

Before After
Width: 260  |  Height: 252  |  Size: 97 KiB

BIN
blogContent/posts/data-science/media/pixel/output_3_0.png View File

Before After
Width: 375  |  Height: 185  |  Size: 56 KiB

BIN
blogContent/posts/data-science/media/pixel/output_4_0.png View File

Before After
Width: 375  |  Height: 185  |  Size: 56 KiB

BIN
blogContent/posts/data-science/media/pixel/output_5_0.png View File

Before After
Width: 260  |  Height: 252  |  Size: 4.4 KiB

BIN
blogContent/posts/data-science/media/pixel/output_9_0.png View File

Before After
Width: 260  |  Height: 252  |  Size: 67 KiB

Loading…
Cancel
Save