An International Platform for perspectives that transcend the traditional Divides between the Humanities and stem    

Mosaic Pictures With Computer Science

Mosaic Pictures With Computer Science

Mosaics are a form of art that focuses on assembling small pieces of materials such as tile, porcelain, or glass into a larger pattern, often with the intent of expressing visual messages or a story in addition to being aesthetically appealing. The history of mosaics can be traced back to 3rd millennium BCE in Mesopotamia, where the purpose of mosaics altered from paving marble pieces on the ground to fortify residences to decorating important structures as shown in the Sumerians’ use of mosaic on temple walls. Influenced by this change, in the 5th or 4th century B.C., the Greeks began to establish mosaic as a method of creating art, and in ancient Rome, the use of mosaics blossomed throughout the empire. From countertops to churches, mosaics were gradually integrated  into everyday life.

Even today, mosaics are still coveted for their remarkable complexity and creativity. The traditional process of creating mosaic artwork is tedious and requires proficiency in multiple facets of design. Fortunately, with the aid of technology, we can generate mosaic pictures using a much easier approach.

Euclidean distance measures the distance between distinct points in dimensions [Fig. 1]. The less the Euclidean distance between two points, the closer they are in the given dimension. A general .jpg picture can be represented by many 1-pixel by 1-pixel squares, with each square represented by the red, green, and blue value of an integer from 0 to 255. Thus, a .jpg picture whose m-pixels by n-pixels can be easily represented through its RGB value with an array [r1,g1,b1,(r2,g2,b2),…,(rmn,gmn,bmn)], and two pictures’ indexes of similarity can be derived from the Euclidean distance between their representative arrays. Given these mathematic tools, mosaic pictures can be generated using computers.

First, the images (in .jpg format) used as “pieces” for the mosaic picture (referred to as the “mosaic pieces”) are loaded and resized to have the same designed size. Then the actual picture is loaded and has its length and width resized to the nearest multiple of the pieces’ side lengths so that it can be dissected perfectly into pieces (referred to as the “picture pieces”) that have  the same dimensions as the mosaic pieces. The picture pieces and mosaic pieces are then expressed in array form and flattened (every element is put into a new array respectively, which signifies that the new array is a one-dimensional array). Each picture piece is labeled from 1 to n, where n is the total amount of picture pieces. A new blank array is created with the dimensions of (number of pieces in a row)*(designed side length for the mosaic pieces) and (number of pieces in a column)*(designed side length for the mosaic pieces). By comparing every picture piece with every mosaic piece, a most similar mosaic piece is assigned to every picture piece. The chosen mosaic pieces are resized and filled into the new blank array in order. When every picture piece has been replaced with a mosaic piece, the array is converted into a .jpg picture and automatically saved.

This algorithm runs fast on personal computers and allows users to control the size of the final picture by giving them the option to establish the desired amount of mosaic pieces in a row and column. Furthermore, it is  easy to change the selection of images for the mosaic pieces. 

Its applications range from everyday art to attracting publicity in major events. Being able to present details while giving a major idea all through picture gives people lasting impressions; it is important as it lets people practice mosaic art themselves by choosing the pictures they want to use, thus allowing this form of art become common. The algorithm can be improved by making it multi-thread. It currently uses only one core of the CPU.

[Fig. 1]

[Fig. 1]

[Fig. 2]

[Fig. 2]

[Fig. 3]

[Fig. 3]

Appendix (program written in Python)

import cv2
import os
import numpy as np
import re
from scipy.spatial.distance import euclidean
from multiprocessing import Pool
def load_image(length):
    #length is the final side length for each loaded image
    piece_names=os.listdir('imgStorage/'+pieceSet)
    loaded=[]
    for individualPiece in piece_names:
        if not re.search(".jpg",individualPiece,re.I):  #Check for .jpg format
            continue
            #if not .jpg, do not process
        try:
            pieceImg=cv2.imread('imgStorage/'+pieceSet+'/'+individualPiece)
            pieceImg=cv2.resize(pieceImg,(length,length),interpolation=cv2.INTER_CUBIC)
            loaded.append(np.array(pieceImg))
        except Exception as exc:
            print(individualPiece+'  '+str(exc))  #print exception for certain file
    return np.array(loaded,dtype=np.uint8)
def get_new_dimensions(picture_dimensions,sideLength):
    picture_dimensions[0]=int(picture_dimensions[0]/sideLength)*sideLength
    picture_dimensions[1]=int(picture_dimensions[1]/sideLength)*sideLength
    return picture_dimensions
def get_distance(imgA,imgB):
    arrayA=imgA.flatten()
    arrayB=imgB.flatten()
    distance=euclidean(arrayA,arrayB)
    return distance
def get_minD_Index(compare_piece):
    currentMin=get_distance(compare_piece,img_pieces[0])
    currentMinIndex=0
    for j in range(1,len(img_pieces)):
        if get_distance(compare_piece,img_pieces[j])<currentMin:
            currentMin=get_distance(compare_piece,img_pieces[j])
            currentMinIndex=j
    return currentMinIndex
def replace_Piece(i):
    picture_section=picture[int((i//piece_col)*sideL):int((i//piece_col+1)*sideL),int((i%piece_col)*sideL):int((i%piece_col+1)*sideL),:]
    newPicture[int((i//piece_col)*pieceL):int((i//piece_col+1)*pieceL),int((i%piece_col)*pieceL):int((i%piece_col+1)*pieceL),:]=usePiece[get_minD_Index(picture_section)]
if __name__ == '__main__':
    pieceSet=str(input('choose the set of pieces: '))
    sideL=int(input('insert side length for disecting the picture: '))
    pieceL=int(input('insert side length for puzzle\'s piece: '))
    img_pieces=load_image(sideL)
    usePiece=load_image(pieceL)
    print('successfully loaded {} images for mosaic piece'.format(len(usePiece)))
    originalName=input('insert the picture\'s name: ')
    global picture
    picture=cv2.imread('Original/'+originalName+'.jpg')
    old_picture_dimensions=list(picture.shape)
    print('old dimensions of the picture↓')
    print(old_picture_dimensions)
    new_picture_dimensions=get_new_dimensions(old_picture_dimensions,sideL)
    #make dimensions the nearest multiple of sideL
    print('modified dimensions of the picture↓')
    print(new_picture_dimensions)
    picture=cv2.resize(picture,(new_picture_dimensions[1],new_picture_dimensions[0]),interpolation=cv2.INTER_CUBIC)
    #resize the picture to its new dimensions
    piece_row=new_picture_dimensions[0]//sideL
    piece_col=new_picture_dimensions[1]//sideL
    newPicture=np.zeros([int(piece_row*pieceL),int(piece_col*pieceL),3],dtype=np.uint8)
    print('final dimensions of the picture↓')
    print(list(newPicture.shape))
    for i in range(piece_row*piece_col):
        replace_Piece(i)
    cv2.imwrite(originalName+'-mosaiced.jpg',newPicture,[int(cv2.IMWRITE_JPEG_QUALITY),90])
    end=input('Complete!')




Ode to Mathematics

Coping With Climate Change