Skip to content

Commit

Permalink
API update
Browse files Browse the repository at this point in the history
  • Loading branch information
Debson committed Nov 18, 2020
1 parent 74a92db commit 1bcb42e
Showing 1 changed file with 88 additions and 46 deletions.
134 changes: 88 additions & 46 deletions ChaosMosaic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,84 +4,109 @@
from random import randint
from PIL import Image
import cv2
from enum import Enum
import tkinter


class ChaosMosaic:
def __init__(self, sampleImagePath, outputImagePath, outputImageSize):
self.sampleImgPath = sampleImagePath
self.outputImagePath = outputImagePath
self.outputImageTargetSize = outputImageSize
class TilePatchSelectMethodType(Enum):
Random = 1,
UserSpecified = 2

class ChaosMosaic:
def __init__(self):
self._keepTilePatchToSampleImageAspectRatio = False
self._sampleImgPath = ""
self._outputImagePath = ""
self._outputImageSize = [512, 512]
self._tilePatchSelectMethodType = TilePatchSelectMethodType.Random
self._minTilePatchSize = 0
self._maxTilePatchSize = 0

def initialize(self):
self._loadImage()

self.minTilePatchSizeFactor = 0.5
self.minTilePatchWidth = floor(self.sampleImageWidth * self.minTilePatchSizeFactor)
self.minTilePatchHeight = floor(self.sampleImageHeight * self.minTilePatchSizeFactor)
def setSampleImagePath(self, sampleImagePath):
self._sampleImgPath = sampleImagePath

def setOutputImagePath(self, outputImagePath):
self._outputImagePath = outputImagePath

def setOutputImageSize(self, outputImageSize):
self._outputImageSize = outputImageSize

def setKeepTilePatchToSampleImageAspectRatio(self, val):
self._keepTilePatchToSampleImageAspectRatio = val

def setMinTilePatchSize(self, minTilePathSize):
self._minTilePatchSize = minTilePathSize

def setMaxTilePatchSize(self, maxTilePathSize):
self._maxTilePatchSize = maxTilePathSize

self.maxTilePatchSizeFactor = 0.8
self.maxTilePatchWidth = floor(self.sampleImageWidth * self.maxTilePatchSizeFactor)
self.maxTilePatchHeight = floor(self.sampleImageHeight * self.maxTilePatchSizeFactor)
def setTilePatchSizeFactor(self, factor):
self._minTilePatchSizeFactor = factor

self.keepTilePatchToSampleImageAspectRatio = False
def setTilePatchSelectMethodType(self, tilePatchSelectMethodType):
self._tilePatchSelectMethodType = tilePatchSelectMethodType

def perform(self, iterations=1, saveToFile=True):
self.outputImage = self._constructTileMatrix()
self._outputImage = self._constructTileMatrix()

for iteration in range(0, iterations):
randomTile = self._getRandomTile()
randomTilePatch = self._getRandomTilePatch(randomTile)
self._insertTilePatchAtRandomLocation(randomTilePatch)

self.outputImage = self.outputImage[0:self.outputImageTargetSize[0], 0:self.outputImageTargetSize[1]]
self._outputImage = self._outputImage[0:self._outputImageTargetSize[0], 0:self._outputImageTargetSize[1]]
if saveToFile:
img = Image.fromarray(np.uint8(self.outputImage * 255))
img.save(self.outputImagePath + 'out.jpg')
img = Image.fromarray(np.uint8(self._outputImage * 255))
img.save(self._outputImagePath + 'out.jpg')

def _loadImage(self):
# Read sample image from file
self.sampleImage = cv2.imread(self.sampleImgPath)
self.sampleImage = cv2.cvtColor(self.sampleImage, cv2.COLOR_BGR2RGB);
self._sampleImage = cv2.imread(self._sampleImgPath)
self._sampleImage = cv2.cvtColor(self._sampleImage, cv2.COLOR_BGR2RGB);

# Normalize the image
self.sampleImage = self.sampleImage / 255.0
self._sampleImage = self._sampleImage / 255.0

# Extract height, width and channels of sample image
self.sampleImageHeight, self.sampleImageWidth, self.sampleImageChannels = np.shape(self.sampleImage)
self._sampleImageHeight, self._sampleImageWidth, self._sampleImageChannels = np.shape(self._sampleImage)

def _constructTileMatrix(self):
# Construct matrix that will be composed from sample images
# that will serve as base output image

self.outputImageWidthMultiplier = ceil(self.outputImageTargetSize[0] / self.sampleImageWidth)
self.outputImageHeightMultiplier = ceil(self.outputImageTargetSize[1] / self.sampleImageHeight)
self.outputImageWidth = self.sampleImageHeight * self.outputImageWidthMultiplier
self.outputImageHeight = self.sampleImageWidth * self.outputImageHeightMultiplier
self._outputImageWidthMultiplier = ceil(self._outputImageTargetSize[0] / self._sampleImageWidth)
self._outputImageHeightMultiplier = ceil(self._outputImageTargetSize[1] / self._sampleImageHeight)
self._outputImageWidth = self._sampleImageHeight * self._outputImageWidthMultiplier
self._outputImageHeight = self._sampleImageWidth * self._outputImageHeightMultiplier

outputImg = np.zeros(
(self.outputImageWidth,
self.outputImageHeight, self.sampleImageChannels), dtype=np.float64)
(self._outputImageWidth,
self._outputImageHeight, self._sampleImageChannels), dtype=np.float64)

for rowIndex in range(0, self.outputImageHeightMultiplier, ):
for colIndex in range(0, self.outputImageWidthMultiplier, ):
outputImg[self.sampleImageHeight * rowIndex: self.sampleImageHeight * (rowIndex + 1),
self.sampleImageWidth * colIndex: self.sampleImageWidth * (colIndex + 1)] = self.sampleImage
for rowIndex in range(0, self._outputImageHeightMultiplier, ):
for colIndex in range(0, self._outputImageWidthMultiplier, ):
outputImg[self._sampleImageHeight * rowIndex: self._sampleImageHeight * (rowIndex + 1),
self._sampleImageWidth * colIndex: self._sampleImageWidth * (colIndex + 1)] = self._sampleImage

return outputImg

def _getRandomTile(self):
# Determine position of complete random tile and copy it

maxTilesHorizontalCount = self.outputImageWidth / self.sampleImageWidth
maxTilesVerticalCount = self.outputImageHeight / self.sampleImageHeight
maxTilesHorizontalCount = self._outputImageWidth / self._sampleImageWidth
maxTilesVerticalCount = self._outputImageHeight / self._sampleImageHeight

randomTileHorizontalIndex = randint(0, maxTilesHorizontalCount - 1)
randomTileVerticalIndex = randint(0, maxTilesVerticalCount - 1)

randomTileLeft = self.sampleImageHeight * randomTileHorizontalIndex
randomTileRight = self.sampleImageHeight * (randomTileHorizontalIndex + 1)
randomTileTop = self.sampleImageHeight * randomTileVerticalIndex
randomTileBottom = self.sampleImageHeight * (randomTileVerticalIndex + 1)
randomTile = self.outputImage[randomTileTop:randomTileBottom, randomTileLeft:randomTileRight]
randomTileLeft = self._sampleImageHeight * randomTileHorizontalIndex
randomTileRight = self._sampleImageHeight * (randomTileHorizontalIndex + 1)
randomTileTop = self._sampleImageHeight * randomTileVerticalIndex
randomTileBottom = self._sampleImageHeight * (randomTileVerticalIndex + 1)
randomTile = self._outputImage[randomTileTop:randomTileBottom, randomTileLeft:randomTileRight]

return randomTile

Expand All @@ -91,11 +116,11 @@ def _getRandomTilePatch(self, tile):

tileHeight, tileWidth, tileChannels = np.shape(tile)

randomTileWidth = randint(self.minTilePatchWidth, self.maxTilePatchWidth)
if self.keepTilePatchToSampleImageAspectRatio:
randomTileWidth = randint(self._minTilePatchSize, self._maxTilePatchSize)
randomTileHeight = randint(self._minTilePatchSize, self._maxTilePatchSize)

if self._keepTilePatchToSampleImageAspectRatio:
randomTileHeight = randomTileWidth
else:
randomTileHeight = randint(self.minTilePatchHeight, self.maxTilePatchHeight)

randomTileX = randint(0, tileWidth - randomTileWidth)
randomTileY = randint(0, tileHeight - randomTileHeight)
Expand All @@ -113,12 +138,12 @@ def _insertTilePatchAtRandomLocation(self, tilePatch):

tilePatchHeight, tilePatchWidth, tilePatchChannels = np.shape(tilePatch)

randomOutputImageX = randint(0, self.outputImageWidth - tilePatchWidth)
randomOutputImageY = randint(0, self.outputImageHeight - tilePatchHeight)
randomOutputImageX = randint(0, self._outputImageWidth - tilePatchWidth)
randomOutputImageY = randint(0, self._outputImageHeight - tilePatchHeight)

print("Tile inserted at: (%d, %d):" % (randomOutputImageX, randomOutputImageY))

self.outputImage[randomOutputImageY:randomOutputImageY + tilePatchHeight,
self._outputImage[randomOutputImageY:randomOutputImageY + tilePatchHeight,
randomOutputImageX:randomOutputImageX + tilePatchWidth] = tilePatch

def _showImage(self, image):
Expand All @@ -128,5 +153,22 @@ def _showImage(self, image):

return 0

chaosMosaic = ChaosMosaic('img/1.jpg', 'out/', [512, 512])
chaosMosaic.perform(900)

class ChaosMosaicGUI:
def __init__(self):
self.chaosMosaicAPI = ChaosMosaic()
self.chaosMosaicAPI.setSampleImagePath('img/1.jpg')
self.chaosMosaicAPI.setOutputImageSize('out/')
self.chaosMosaicAPI.setOutputImageSize([512, 512])

def show(self):
self._window = tkinter.Tk()
self._window.title("Chaos Mosaic")
self._startButton =


m.mainloop()


chaosMosaicGUI = ChaosMosaicGUI()
chaosMosaicGUI.show()

0 comments on commit 1bcb42e

Please sign in to comment.