1 of 16

Paint By Numbers, Coloring Book Sim

Paint-by-Numbers Interface, Using Kuwahara Filter, Gaussian Blur, K-Means Clustering, and a Textured Painting Style

1

Group 20: Vivan Sinha, Kyle Cheng, Robert Ni, Keira Swei

CS184, Spring 2025

2 of 16

Paint by Numbers Motivation

  • Growing up, we all loved coloring books.
  • What if we could color in whatever image we wanted?

3 of 16

Starting Point

  • We started from scratch
  • Implemented everything ourselves, using standard libraries and referencing pseudocode
  • Learned about image processing and representations, clustering algorithms, algorithm integration, and frontend design.

4 of 16

Paint by Numbers Pipeline

Original Image

Kuwahara Filter

Gaussian Blur

K-Means Clustering (k=5)

5 of 16

Kuwahara Filter

  • Used to smooth out image details
  • Algorithm (use an HSV image)
    • Create square window around a pixel
    • Divide window into four quadrants
    • Find standard deviation of the V channel of pixels in each quadrant
    • Set the central pixel’s HSV to be the average of pixels from the quadrant with the lowest standard deviation
  • Issues:
    • Speed: decided to skip every other pixel
    • Aliasing: decided to use Gaussian blur

6 of 16

Gaussian Blur

  • Used to smooth out block artifacts from a Kuwahara filter by removing high frequencies in the image
  • Algorithm:
    • Pass 1: convolve 1D kernel in horizontal direction
    • Pass 2: convolve in vertical direction

7 of 16

K-Means Clustering

  • Pixel RGB values are the data points
  • Algorithm:
    • Randomly select k centroids
    • Until convergence or a max number of iterations is reached:
      • Assign each data point to the nearest cluster (based on closest centroid)
      • Update centroids to be the mean of the points in each cluster
  • Final Result: All pixel colors in the final image are replaced by the color of the centroid of their assigned cluster, resulting in exactly k colors.

k=2

k=3

k=20

k=3

8 of 16

9 of 16

Region Clustering

  • First we use flood fill to grow regions based on adjacent pixels with the same color, and once a region is found it is assigned its color
  • Once all regions are found, regions under a certain number of pixels are joined with the neighbor with the most adjacent pixels.
  • This gives the UI groups of pixels with set colors, which it can then use to figure out where to clip user strokes to ensure we color within the lines.

https://codeheir.com/2022/08/21/comparing-flood-fill-algorithms-in-javascript/

10 of 16

UI

  • Three stacked <canvas> elements:
  • Base Canvas: Stores the user’s actual painting strokes
  • Highlight Canvas: Renders outlines for regions and overlays unselected regions in gray to guide the user
  • Cursor Canvas: Displays a real-time preview of the brush position and shape, including color and size
  • Key-Features: region-based painting, smooth round brush with adjustable size, color palette display, outline toggle, auto select color mode, hotkey color switching, and download functionality

11 of 16

Brush Stroke Detailing

  • Draw many little dots under the cursor instead of one big dot.
  • Linearly interpolate random positions between the cursor's previous and current position.
  • Number of dots = distance / brush width
  • More realistic
    • Little dots improve texture and simulate brush bristles
  • Better control
    • Re-paint over areas

to make it darker

(like layering paint)

12 of 16

13 of 16

Ryan REyNolds

14 of 16

Kylo REN

15 of 16

RENaldo

16 of 16

Thank you!

Barbie & REN