import sys import cv import Image import gameduino import gameduino.prep as gdprep import gameduino.sim as gdsim def cvcast(mat, newtype): """ Convert mat to new image type newtype """ r = cv.CreateMat(mat.rows, mat.cols, newtype) cv.Convert(mat, r) return r def tile_encode(image888, tilecount = 255): im = cvcast(image888, cv.CV_32FC3) xys = [(x,y) for y in range(0, im.rows, 8) for x in range(0, im.cols, 8)] tiles = [cv.GetSubRect(im, (x, y, 8, 8)) for (x,y) in xys] yrb = cv.CreateMat(8, 8, cv.CV_32FC3) (yy, uu, vv) = [cv.CreateMat(8, 8, cv.CV_32FC1) for i in range(3)] dct = cv.CreateMat(8, 8, cv.CV_32FC1) # each row in samples is a point in the 192 dimensional space samples = cv.CreateMat(len(xys), 192, cv.CV_32FC1) for row,tile in enumerate(tiles): cv.CvtColor(tile, yrb, cv.CV_BGR2YCrCb) cv.Split(yrb, yy, uu, vv, None) # Paste the DCT of Y,U,V into a row of matrix 'samples' for (chan, column, weight) in [(yy, 0, 1.0), (uu, 64, 0.5), (vv, 128, 0.5)]: cv.DCT(chan, dct, cv.CV_DXT_FORWARD) cv.Scale(cv.Reshape(dct, 1, 1), cv.GetSubRect(samples, (column, row, 64, 1)), weight) labels = cv.CreateMat(len(xys), 1, cv.CV_32SC1) tc = (cv.CV_TERMCRIT_ITER, 10, 0.0) cv.KMeans2(samples, tilecount, labels, tc, flags = 2) labels = [int(labels[i,0]) for i in range(len(xys))] def haslabel(l): # which tiles got label l return [t for (t, i) in zip(tiles, labels) if (l == i)] # Construct the mean tile for each label def tilemean(tiles): """ compute the mean of a list of tile images """ s = cv.CreateMat(8, 8, cv.CV_32FC3) cv.SetZero(s) for t in tiles: cv.Add(s, t, s) cv.Scale(s, s, 1.0 / len(tiles)); return cvcast(s, cv.CV_8UC3) merged = dict([(l, tilemean(haslabel(l))) for l in set(labels)]) # write the tiles into a new image and return it out = cv.CreateMat(im.rows, im.cols, cv.CV_8UC3) for i,(x,y) in enumerate(xys): cv.Copy(merged[labels[i]], cv.GetSubRect(out, (x,y,8,8))) return out def cv2pil(cvim): cvrgb = cv.CreateMat(cvim.rows, cvim.cols, cv.CV_8UC3) cv.CvtColor(cvim, cvrgb, cv.CV_BGR2RGB) return Image.fromstring("RGB", (cvim.cols, cvim.rows), cvrgb.tostring()) def preview(imsz,picd,chrd,pald): """ Use the Gameduino simulator to return a preview image """ gd = gdsim.Gameduino() gd.fill(gameduino.RAM_PIC, 0xff, 64 * 64) ls = imsz[0] / 8 for y in range(imsz[1] / 8): gd.wrstr(64 * y + gameduino.RAM_PIC, picd[ls*y:ls*y+ls]) gd.wrstr(gameduino.RAM_CHR, chrd) gd.wrstr(gameduino.RAM_PAL, pald) return gd.im() if __name__ == "__main__": im = cv.LoadImageM(sys.argv[1]) (picd,chrd,pald) = gdprep.encode(cv2pil(tile_encode(im, 255))) preview((im.cols, im.rows), picd,chrd,pald).crop((0,0,im.cols,im.rows)).save("out.png")