Created
March 19, 2019 14:09
-
-
Save Groot90/09d07ba43939382d93e97d0dce43112b to your computer and use it in GitHub Desktop.
Python, SVD for image compression example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ''' | |
| Objective: | |
| Using SVD for image compression | |
| ''' | |
| import numpy | |
| from PIL import Image | |
| # FUNCTION DEFINTIONS: | |
| # open the image and return 3 matrices, each corresponding to one channel (R, G and B channels) | |
| def openImage(imagePath): | |
| imOrig = Image.open(imagePath) | |
| im = numpy.array(imOrig) | |
| aRed = im[:, :, 0] | |
| aGreen = im[:, :, 1] | |
| aBlue = im[:, :, 2] | |
| return [aRed, aGreen, aBlue, imOrig] | |
| # compress the matrix of a single channel | |
| def compressSingleChannel(channelDataMatrix, singularValuesLimit): | |
| uChannel, sChannel, vhChannel = numpy.linalg.svd(channelDataMatrix) | |
| aChannelCompressed = numpy.zeros((channelDataMatrix.shape[0], channelDataMatrix.shape[1])) | |
| k = singularValuesLimit | |
| leftSide = numpy.matmul(uChannel[:, 0:k], numpy.diag(sChannel)[0:k, 0:k]) | |
| aChannelCompressedInner = numpy.matmul(leftSide, vhChannel[0:k, :]) | |
| aChannelCompressed = aChannelCompressedInner.astype('uint8') | |
| return aChannelCompressed | |
| # MAIN PROGRAM: | |
| print ('*** Image Compression using SVD - a demo') | |
| aRed, aGreen, aBlue, originalImage = openImage('lena.png') | |
| # image width and height: | |
| imageWidth = 512 | |
| imageHeight = 512 | |
| #number of singular values to use for reconstructing the compressed image | |
| singularValuesLimit = 160 | |
| aRedCompressed = compressSingleChannel(aRed, singularValuesLimit) | |
| aGreenCompressed = compressSingleChannel(aGreen, singularValuesLimit) | |
| aBlueCompressed = compressSingleChannel(aBlue, singularValuesLimit) | |
| imr=Image.fromarray(aRedCompressed,mode=None) | |
| img=Image.fromarray(aGreenCompressed,mode=None) | |
| imb=Image.fromarray(aBlueCompressed,mode=None) | |
| newImage = Image.merge("RGB", (imr,img,imb)) | |
| originalImage.show() | |
| newImage.show() | |
| # CALCULATE AND DISPLAY THE COMPRESSION RATIO | |
| mr = imageHeight | |
| mc = imageWidth | |
| originalSize = mr * mc * 3 | |
| compressedSize = singularValuesLimit * (1 + mr + mc) * 3 | |
| print('original size:') | |
| print(originalSize) | |
| print('compressed size:') | |
| print(compressedSize) | |
| print('Ratio compressed size / original size:') | |
| ratio = compressedSize * 1.0 / originalSize | |
| print(ratio) | |
| print('Compressed image size is ' + str( round(ratio * 100 ,2)) + '% of the original image ' ) | |
| print('DONE - Compressed the image! Over and out!') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment