-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5eed6f9
commit c8665d1
Showing
12 changed files
with
6,123 additions
and
2 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import scipy | ||
import gzip,cPickle | ||
import correlation | ||
import os,pdb,glob | ||
import theano | ||
import skimage | ||
import sklearn | ||
import PIL.Image | ||
import pylab | ||
|
||
import scipy.ndimage as ndi | ||
import numpy as np | ||
import matplotlib.pyplot as plt | ||
import matplotlib.cm as cm | ||
import matplotlib.font_manager as font_manager | ||
|
||
from sklearn import preprocessing, cross_validation | ||
from sklearn.feature_extraction import image | ||
from sklearn.decomposition import PCA | ||
from scipy import io as sp_io | ||
from numpy.random import RandomState | ||
from theano import tensor as T | ||
from scipy import misc | ||
from PIL import Image, ImageEnhance | ||
from pylab import * | ||
from theano.tensor.nnet import conv | ||
from scipy.misc import lena | ||
from itertools import product | ||
|
||
################################################# | ||
# Generating fully overlapping patches # | ||
################################################# | ||
|
||
def overlapping_patches(path, patch_size): | ||
|
||
Ols_images = Image.open (path).convert('L') | ||
height, width = np.asarray(Ols_images).shape | ||
|
||
if height < 512: | ||
Ols_images = Ols_images.resize((512, 512), Image.BICUBIC) | ||
print '... image resized to 512,512' | ||
elif height > 512: | ||
Ols_images = Ols_images.resize((512, 512), Image.ANTIALIAS) | ||
print '... image resized to 512,512' | ||
|
||
Ols_images = np.asarray(Ols_images,dtype = 'float') | ||
Ols_images = correlation.normalizeArray(np.asarray(Ols_images)) | ||
|
||
image_height = np.asarray(Ols_images).shape[0] | ||
image_width = np.asarray(Ols_images).shape[1] | ||
|
||
Ols_patche = image.extract_patches_2d(image=Ols_images, patch_size=patch_size,max_patches=None) | ||
Ols_patches = np.reshape(Ols_patche,(Ols_patche.shape[0], -1)) | ||
n_patches, nvis = Ols_patches.shape | ||
rval = (Ols_patches, image_height, image_width) | ||
return rval | ||
|
||
################################################# | ||
# Generating overlapping patches with strides # | ||
################################################# | ||
|
||
def overlapping_patches_strides(path, patch_size, strides): | ||
|
||
Ols_images = Image.open (path).convert('L') | ||
height, width = np.asarray(Ols_images).shape | ||
|
||
'''if height < 512: | ||
Ols_images = Ols_images.resize((512, 512), Image.BICUBIC) | ||
print '... image resized to 512,512' | ||
elif height > 512: | ||
Ols_images = Ols_images.resize((512, 512), Image.ANTIALIAS) | ||
print '... image resized to 512,512' | ||
''' | ||
|
||
#nrow = 512 | ||
#ncol = 512 #767 #768 for 28x281 767 for 17x17 | ||
|
||
# ROC Pic | ||
nrow = height*1 | ||
ncol = width*1 | ||
|
||
#print ' ... Initial image dimensions: ', nrow, ncol | ||
|
||
Up = (nrow-patch_size[0]-strides[0])/strides[0] | ||
Vp = (ncol-patch_size[1]-strides[1])/strides[1] | ||
|
||
#print ' ... Initial patches: ', '%.2f'%(Up), '%.2f'%(Vp) | ||
|
||
Up = np.floor((nrow-patch_size[0]-strides[0])/strides[0]) | ||
Vp = np.floor((ncol-patch_size[1]-strides[1])/strides[1]) | ||
|
||
#print ' ... Generated patches: ', '%.2f'%(Up), '%.2f'%(Vp) | ||
|
||
nrow = np.int(Up*strides[0] + strides[0] + patch_size[0]) | ||
ncol = np.int(Vp*strides[1] + strides[1] + patch_size[1]) | ||
|
||
#print ' ... Resized image dimensions: ', nrow, ncol | ||
|
||
Ols_images = Ols_images.resize((ncol, nrow), Image.BICUBIC) | ||
|
||
Ols_images = np.asarray(Ols_images,dtype = 'float') | ||
Ols_images = correlation.normalizeArray(np.asarray(Ols_images)) | ||
U = (nrow-patch_size[0]-strides[0])/strides[0] | ||
V = (ncol-patch_size[1]-strides[1])/strides[1] | ||
|
||
image_height = np.asarray(Ols_images).shape[0] | ||
image_width = np.asarray(Ols_images).shape[1] | ||
|
||
Ols_patche = image.extract_patches(Ols_images, patch_shape=patch_size, extraction_step=strides) | ||
Ols_patches = np.reshape(Ols_patche,(Ols_patche.shape[0]*Ols_patche.shape[1], -1)) | ||
|
||
n_patches, nvis = Ols_patches.shape | ||
rval = (Ols_patches, image_height, image_width) | ||
return rval | ||
|
||
################################################# | ||
# Reconstructing pathes with strides # | ||
################################################# | ||
|
||
def reconstruct_from_patches_with_strides_2d(patches, image_size, strides): | ||
|
||
i_stride = strides[0] | ||
j_stride = strides[1] | ||
i_h, i_w = image_size[:2] | ||
p_h, p_w = patches.shape[1:3] | ||
img = np.zeros(image_size) | ||
img1 = np.zeros(image_size) | ||
n_h = int((i_h - p_h + i_stride)/i_stride) | ||
n_w = int((i_w - p_w + j_stride)/j_stride) | ||
for p, (i, j) in zip(patches, product(range(n_h), range(n_w))): | ||
img[i*i_stride:i*i_stride + p_h, j*j_stride:j*j_stride + p_w] +=p | ||
img1[i*i_stride:i*i_stride + p_h, j*j_stride:j*j_stride + p_w] +=np.ones(p.shape) | ||
return img/img1 | ||
|
||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,53 @@ | ||
# LLNet | ||
A low light image enhancement with deep learning | ||
# LLNet: Low-light Image Enhancement with Deep Learning # | ||
|
||
This repository includes the codes and modules used for running LLNet via a Graphical User Interface. Users can choose to train the network from scratch, or to enhance multiple images using a specific trained model. | ||
|
||
NOTE: Trained model 17x17 is included in this repo. | ||
|
||
## How do I run the program? ## | ||
|
||
Open the terminal and navigate to this directory. Type: | ||
|
||
``` | ||
#!bash | ||
python llnet.py | ||
``` | ||
|
||
to launch the program with GUI. For command-line only interface, you type the following command in the terminal. | ||
|
||
To train a new model, enter: | ||
|
||
``` | ||
#!bash | ||
python llnet.py train [TRAINING_DATA] | ||
``` | ||
|
||
To enhance an image, enter: | ||
|
||
``` | ||
#!bash | ||
python llnet.py test [IMAGE_FILENAME] [MODEL_FILENAME] | ||
``` | ||
|
||
For example, you may type: | ||
|
||
``` | ||
#!bash | ||
python llnet.py train datafolder/yourdataset.mat | ||
python llnet.py test somefolder/darkpicture.png models/save_model.obj | ||
``` | ||
|
||
where file names do not need to be in quotes. | ||
|
||
Datasets need to be saved as .MAT file with the '-v7.3' tag in MATLAB. The saved variables are: | ||
|
||
``` | ||
train_set_x (N x wh) Noisy, darkened training data | ||
train_set_y (N x wh) Clean, bright training data | ||
valid_set_x (N x wh) Noisy, darkened validation data | ||
valid_set_y (N x wh) Clean, bright validation data | ||
test_set_x (N x wh) Noisy, darkened test data | ||
test_set_y (N x wh) Clean, bright test data | ||
``` | ||
|
||
Where N is the number of examples and w, h are the width and height of the patches, respectively. Test data are mostly used to plot the test patches; in actual applications we are interested to enhance a single image. Use the test command instead. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from easygui import * | ||
pass | ||
__all__ = easygui.__all__ |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
""" | ||
correlation.py | ||
Compute the correlation between two, single-channel, grayscale input images. | ||
The second image must be smaller than the first. | ||
Author: Brad Montgomery | ||
http://bradmontgomery.net | ||
This code has been placed in the public domain by the author. | ||
USAGE: python correlation <image file> <match file> | ||
""" | ||
#import Image | ||
import numpy | ||
import math | ||
import sys | ||
import timeit | ||
|
||
def normalizeArray(a): | ||
""" | ||
Normalize the given array to values between 0 and 1. | ||
Return a numpy array of floats (of the same shape as given) | ||
""" | ||
w,h = a.shape | ||
minval = a.min() | ||
if minval < 0: # shift to positive... | ||
a = a + abs(minval) | ||
maxval = a.max() # THEN, get max value! | ||
new_a = numpy.zeros(a.shape, 'd') | ||
for x in range(0,w): | ||
for y in range(0,h): | ||
new_a[x,y] = float(a[x,y])/maxval | ||
return new_a | ||
|
||
def pil2array(im): | ||
""" Convert a 1-channel grayscale PIL image to a numpy ndarray """ | ||
data = list(im.getdata()) | ||
w,h = im.size | ||
A = numpy.zeros((w*h), 'd') | ||
i=0 | ||
for val in data: | ||
A[i] = val | ||
i=i+1 | ||
A=A.reshape(w,h) | ||
return A | ||
|
||
def array2pil(A,mode='L'): | ||
""" | ||
Convert a numpy ndarray to a PIL image. | ||
Only grayscale images (PIL mode 'L') are supported. | ||
""" | ||
w,h = A.shape | ||
# make sure the array only contains values from 0-255 | ||
# if not... fix them. | ||
if A.max() > 255 or A.min() < 0: | ||
A = normalizeArray(A) # normalize between 0-1 | ||
A = A * 255 # shift values to range 0-255 | ||
if A.min() >= 0.0 and A.max() <= 1.0: # values are already between 0-1 | ||
A = A * 255 # shift values to range 0-255 | ||
A = A.flatten() | ||
data = [] | ||
for val in A: | ||
if val is numpy.nan: val = 0 | ||
data.append(int(val)) # make sure they're all int's | ||
im = Image.new(mode, (w,h)) | ||
im.putdata(data) | ||
return im | ||
|
||
def correlation(input, match): | ||
""" | ||
Calculate the correlation coefficients between the given pixel arrays. | ||
input - an input (numpy) matrix representing an image | ||
match - the (numpy) matrix representing the image for which we are looking | ||
""" | ||
t = timeit.Timer() | ||
assert match.shape < input.shape, "Match Template must be Smaller than the input" | ||
c = numpy.zeros(input.shape) # store the coefficients... | ||
mfmean = match.mean() | ||
iw, ih = input.shape # get input image width and height | ||
mw, mh = match.shape # get match image width and height | ||
|
||
print "Computing Correleation Coefficients..." | ||
start_time = t.timer() | ||
|
||
for i in range(0, iw): | ||
for j in range(0, ih): | ||
|
||
# find the left, right, top | ||
# and bottom of the sub-image | ||
if i-mw/2 <= 0: | ||
left = 0 | ||
elif iw - i < mw: | ||
left = iw - mw | ||
else: | ||
left = i | ||
|
||
right = left + mw | ||
|
||
if j - mh/2 <= 0: | ||
top = 0 | ||
elif ih - j < mh: | ||
top = ih - mh | ||
else: | ||
top = j | ||
|
||
bottom = top + mh | ||
|
||
# take a slice of the input image as a sub image | ||
sub = input[left:right, top:bottom] | ||
assert sub.shape == match.shape, "SubImages must be same size!" | ||
localmean = sub.mean() | ||
temp = (sub - localmean) * (match - mfmean) | ||
s1 = temp.sum() | ||
temp = (sub - localmean) * (sub - localmean) | ||
s2 = temp.sum() | ||
temp = (match - mfmean) * (match - mfmean) | ||
s3 = temp.sum() | ||
denom = s2*s3 | ||
if denom == 0: | ||
temp = 0 | ||
else: | ||
temp = s1 / math.sqrt(denom) | ||
|
||
c[i,j] = temp | ||
|
||
end_time = t.timer() | ||
print "=> Correlation computed in: ", end_time - start_time | ||
print '\tMax: ', c.max() | ||
print '\tMin: ', c.min() | ||
print '\tMean: ', c.mean() | ||
return c | ||
|
||
def main(f1, f2, output_file="CORRELATION.jpg"): | ||
""" open the image files, and compute their correlation """ | ||
im1 = f1.convert('L') | ||
im2 = f2.convert('L') | ||
# Better way to do PIL-Numpy conversion | ||
f = numpy.asarray(im1) # was f = pil2array(im1) | ||
w = numpy.asarray(im2) # was w = pil2array(im2) | ||
corr = correlation(f,w) # was c = array2pil(correlation(f,w)) | ||
c = Image.fromarray(numpy.uint8(normalizeArray(corr) * 255)) | ||
|
||
print "Saving as: %s" % output_file | ||
c.save(output_file) | ||
|
||
if __name__ == "__main__": | ||
if len(sys.argv) == 3: | ||
main(sys.argv[1], sys.argv[2]) | ||
else: | ||
print 'USAGE: python correlation <image file> <match file>' | ||
|
Oops, something went wrong.