コード例 #1
0
    def __init__(self, markerOrder = 4, defaultKernelSize = 21, scalingParameter = 2500):
        # Initialize camera driver.
        # Open output window.
#        cv.NamedWindow('filterdemo', cv.CV_WINDOW_NORMAL)
#	cv.NamedWindow('temp_kernel', cv.CV_WINDOW_NORMAL)
#	cv.NamedWindow('small_image', cv.CV_WINDOW_NORMAL)

#        self.setResolution()


        # Storage for image processing.
        self.currentFrame = None
        self.processedFrame = None
        self.running = True
        # Storage for trackers.
        self.trackers = []
        self.windowedTrackers = []
        self.oldLocations = []
        # Initialize trackers.
#        for markerOrder in markerOrders:
        temp = ImageAnalyzer(downscaleFactor=1)
        temp.addMarkerToTrack(markerOrder, defaultKernelSize, scalingParameter)
        self.trackers.append(temp)
        self.windowedTrackers.append(TrackerInWindowMode(markerOrder, defaultKernelSize))
        self.oldLocations.append(MarkerPose(None, None, None, None))
        self.cnt = 0
        self.defaultOrientation = 0
コード例 #2
0
    def __init__(self, markerOrders = [7, 8], defaultKernelSize = 21, scalingParameter = 2500, cameraNumber = 0):
        # Initialize camera driver.

        # Open output window.
        cv.NamedWindow('filterdemo', cv.CV_WINDOW_AUTOSIZE)

        self.setFocus(cameraNumber)
        self.camera = cv.CaptureFromCAM(cameraNumber)
        self.setResolution()

        # Storage for image processing.
        self.currentFrame = None
        self.processedFrame = None
        self.running = True

        # Storage for trackers.
        self.trackers = []
        self.oldLocations = []

        # Initialize trackers.
        for markerOrder in markerOrders:
            temp = ImageAnalyzer(downscaleFactor=1)
            temp.addMarkerToTrack(markerOrder, defaultKernelSize, scalingParameter)
            self.trackers.append(temp)
            self.oldLocations.append(MarkerPose(None, None, None, None))

        self.cnt = 0
        self.defaultOrientation = 0
コード例 #3
0
    def __init__(self,
                 markerOrders=[7, 8],
                 defaultKernelSize=21,
                 scalingParameter=2500):
        # Initialize camera driver.
        # Open output window.
        cv.NamedWindow('filterdemo', cv.CV_WINDOW_AUTOSIZE)

        self.setFocus()
        # Select the camera where the images should be grabbed from.
        self.camera = cv.CaptureFromCAM(0)
        #self.setResolution()

        # Storage for image processing.
        self.currentFrame = None
        self.processedFrame = None
        self.running = True
        # Storage for trackers.
        self.trackers = []
        self.oldLocations = []

        # Initialize trackers.
        for markerOrder in markerOrders:
            temp = ImageAnalyzer(downscaleFactor=1)
            temp.addMarkerToTrack(markerOrder, defaultKernelSize,
                                  scalingParameter)
            self.trackers.append(temp)
            self.oldLocations.append(MarkerPose(None, None, None, None))

        self.cnt = 0
        self.defaultOrientation = 0
コード例 #4
0
    def __init__(self, markerOrders = [7, 8], defaultKernelSize = 21, scalingParameter = 2500):
        # Initialize camera driver.
        # Open output window.
        cv2.namedWindow('filterdemo', cv2.cv.CV_WINDOW_AUTOSIZE)

        self.setFocus()
        # Select the camera where the images should be grabbed from.
        self.camera = cv2.VideoCapture(0)
        self.setResolution()

        # Storage for image processing.
        self.currentFrame = None
        self.processedFrame = None
        self.running = True
        # Storage for trackers.
        self.trackers = []
        self.windowedTrackers = []
        self.oldLocations = []
        # Initialize trackers.
        for markerOrder in markerOrders:
            temp = ImageAnalyzer(downscaleFactor=1)
            temp.addMarkerToTrack(markerOrder, defaultKernelSize, scalingParameter)
            self.trackers.append(temp)
            self.windowedTrackers.append(TrackerInWindowMode(markerOrder, defaultKernelSize))
            self.oldLocations.append(MarkerPose(None, None, None, None))
        self.cnt = 0
        self.defaultOrientation = 0    
コード例 #5
0
    def __init__(self, store_pics=False):
        self.cam = picamera.PiCamera()
        self.cam.resolution = (resolution['x'], resolution['y'])
        self.analyzer = ImageAnalyzer(adaptive_threshold=True)
        self.logger = Log.instance('TargetDetection')
        self.store_pics = store_pics

        if os.path.exists(dir_name):
            shutil.rmtree(dir_name)
        os.makedirs(dir_name)
コード例 #6
0
def estimate_distances(pics_dir):
    analyzer = ImageAnalyzer()
    for (path, _, files) in os.walk(pics_dir):
        for f in sorted(files):
            pic = os.path.join(path, f)
            img = cv2.imread(pic)
            try:
                px, mm = analyzer.calculate_distance(img)
                logger.debug('distance: {:4d}px\t{:3.0f}mm'.format(px, mm))
            except Exception as e:
                logger.error(e)
コード例 #7
0
def process(pics_dir, adaptive_threshold):
    analyzer = ImageAnalyzer(adaptive_threshold=adaptive_threshold)
    timings = []
    for (path, _, files) in os.walk(pics_dir):
        for f in sorted(files):
            pic = os.path.join(path, f)
            img = cv2.imread(pic)
            try:
                start = time.process_time()
                px, mm = analyzer.calculate_distance(img)
                end = time.process_time()
                timings.append(int((end - start) * 1000))
                logger.debug('distance: {:4d}px\t{:3.0f}mm'.format(px, mm))
            except Exception as e:
                logger.error(e)
    return timings
コード例 #8
0
 def display_image(self):
     indexes = self.table_view_sm.selectedIndexes()
     index = indexes[0]
     file_name = str(index.data())
     if (file_name.endswith("fits") or file_name.endswith("fit")):
         file_with_path = os.path.join(self.current_directory.cur_dir_path,
                                       file_name)
         self.im_disp = ImageAnalyzer(file_with_path, parent=self)
コード例 #9
0
    def __init__(self,
                 markerOrders=[7, 8],
                 defaultKernelSize=21,
                 scalingParameter=2500,
                 cameraDevice=0):
        # Initialize camera driver.
        # Open output window.
        #        cv.NamedWindow('filterdemo', cv.CV_WINDOW_AUTOSIZE)
        cv.NamedWindow('filterdemo', cv.CV_WINDOW_NORMAL)
        #        cv.NamedWindow('filterdemo', cv.CV_WINDOW_AUTOSIZE)
        cv.NamedWindow('temp_kernel', cv.CV_WINDOW_NORMAL)
        cv.NamedWindow('small_image', cv.CV_WINDOW_NORMAL)

        self.cameraDevice = cameraDevice

        # If an interface has been given to the constructor, it's a camdevice and we need to set some properties. If it's not, it means it's a file.
        if (isinstance(cameraDevice, numbers.Integral)):
            self.setFocus()
            # Select the camera where the images should be grabbed from.
            self.camera = cv.CaptureFromCAM(cameraDevice)
        else:
            self.camera = cv.CaptureFromFile(cameraDevice)
        self.setResolution()

        # Storage for image processing.
        self.currentFrame = None
        self.processedFrame = None
        self.running = True
        # Storage for trackers.
        self.trackers = []
        self.windowedTrackers = []
        self.oldLocations = []
        # Initialize trackers.
        for markerOrder in markerOrders:
            temp = ImageAnalyzer(downscaleFactor=1)
            temp.addMarkerToTrack(markerOrder, defaultKernelSize,
                                  scalingParameter)
            self.trackers.append(temp)
            self.windowedTrackers.append(
                TrackerInWindowMode(markerOrder, defaultKernelSize))
            self.oldLocations.append(MarkerPose(None, None, None, None))
        self.cnt = 0
        self.defaultOrientation = 0
コード例 #10
0
	def __init__(self, input_PIL_img, lib_Lab_vectors, photoLog, cellLog, subimage, progress=0):
		# Set instance variables
		self.input = input_PIL_img
		self.photoLog = photoLog # The photoLog, cellLog, and progress should probably be in it's own information expert
		self.cellLog = cellLog
		self.progress = int(progress)
		self.ImgAnalyzer = ImageAnalyzer()
		self.ImgFinder = ImageFinder(lib_Lab_vectors)
		self.ImgLoader = ImageLoader()
		self.subimage = subimage
コード例 #11
0
def main():
    print("***** Assignment 2 Initiated")
    analyzer = ImageAnalyzer(DATA_DIR, DEPS_DIR, OUTPUT_DIR)

    # ------------------------------------------------------------------------------------------------------------------
    # ---------------------------  SET PATH AND NAMES FOR ALL IMAGE TYPES
    # ------------------------------------------------------------------------------------------------------------------
    print("***** Importing and Undistorting/Demoscaicing Raw Images")
    image_names = []
    # image_names.append(['mono_left', 'mono_left'])
    # image_names.append(['mono_rear', 'mono_rear'])
    # image_names.append(['mono_right', 'mono_right'])
    # image_names.append(['stereo/centre', 'stereo'])
    image_names.append(['stereo/left', 'stereo'])
    # image_names.append(['stereo/right', 'stereo'])
    for name in image_names:
        analyzer.undistortImages(name[0], name[1])

    # ------------------------------------------------------------------------------------------------------------------
    # --------------------------- SAVE IMAGES
    # ------------------------------------------------------------------------------------------------------------------
    print("***** Saving Undistorted/Demoscaiced Images")
    # analyzer.saveImages()

    # ------------------------------------------------------------------------------------------------------------------
    # --------------------------- GENERATE 3D POINT CLOUDS FOR ENTIRE TIME PERIOD
    # ------------------------------------------------------------------------------------------------------------------
    print("***** Generating 3D Point Cloud")
    ptcloud_names = []
    ptcloud_names.append(['lms_front', 'gps/ins.csv'])
    # ptcloud_names.append(['lms_rear', 'gps/ins.csv'])
    # ptcloud_names.append(['ldmrs', 'gps/ins.csv'])
    # for name in ptcloud_names:
    #     analyzer.buildLidarPointCloud(name[0], name[1])

    # ------------------------------------------------------------------------------------------------------------------
    # ---------------------------  SAVE 3D POINT CLOUDS
    # ------------------------------------------------------------------------------------------------------------------
    print("***** Saving 3D Point Clouds")
    analyzer.saveRawLidarPointClouds()

    # ------------------------------------------------------------------------------------------------------------------
    # ---------------------------  PROJECT POINT CLOUDS ONTO IMAGES AND SAVE FIGURE
    # ------------------------------------------------------------------------------------------------------------------
    print("***** Projecting Point Clouds On Images")
    for cloud_type in ptcloud_names:
        for img_type in image_names:
            analyzer.showPointCloudsOnImages(img_type[0], cloud_type[0], cloud_type[1])

    print("***** Assignment 2 Complete")
コード例 #12
0
    def __init__(self, markerOrders = [7, 8], defaultKernelSize = 21, scalingParameter = 2500, cameraDevice=0):
        # Initialize camera driver.
        # Open output window.
#        cv.NamedWindow('filterdemo', cv.CV_WINDOW_AUTOSIZE)
        cv.NamedWindow('filterdemo', cv.CV_WINDOW_NORMAL)
#        cv.NamedWindow('filterdemo', cv.CV_WINDOW_AUTOSIZE)
	cv.NamedWindow('temp_kernel', cv.CV_WINDOW_NORMAL)
	cv.NamedWindow('small_image', cv.CV_WINDOW_NORMAL)


	self.cameraDevice = cameraDevice

	# If an interface has been given to the constructor, it's a camdevice and we need to set some properties. If it's not, it means it's a file.
	if(isinstance(cameraDevice, numbers.Integral)):
	        self.setFocus()
	        # Select the camera where the images should be grabbed from.
	        self.camera = cv.CaptureFromCAM(cameraDevice)
	else:
		self.camera = cv.CaptureFromFile(cameraDevice)
        self.setResolution()


        # Storage for image processing.
        self.currentFrame = None
        self.processedFrame = None
        self.running = True
        # Storage for trackers.
        self.trackers = []
        self.windowedTrackers = []
        self.oldLocations = []
        # Initialize trackers.
        for markerOrder in markerOrders:
            temp = ImageAnalyzer(downscaleFactor=1)
            temp.addMarkerToTrack(markerOrder, defaultKernelSize, scalingParameter)
            self.trackers.append(temp)
            self.windowedTrackers.append(TrackerInWindowMode(markerOrder, defaultKernelSize))
            self.oldLocations.append(MarkerPose(None, None, None, None))
        self.cnt = 0
        self.defaultOrientation = 0
コード例 #13
0
	def get(self, userId, photoId):
		# Get Access Token and Photo URL from header
		access_token = self.request.headers["access-token"]
		photo_url = self.request.headers["photo-url"]
		
		# Load PIL image from facebook url
		im = ImageLoader().load_url_image(photo_url)
		
		# Crop image to a square
		cols, rows = im.size
		
		# Landscape Layout (or Square)
		if cols >= rows:
			target_cols = rows
			left = (cols-target_cols)/2
			right = left+target_cols
			im = im.crop( (left, 0, right, rows) )
			
		# Portrait Layout
		else:
			target_rows = cols
			upper = (rows-target_rows)/2
			lower = upper+target_rows
			im = im.crop( (0, upper, cols, lower) )
		
		# Analyze image
		imgAnalyzer = ImageAnalyzer()
		cols, rows = im.size
		labVec = imgAnalyzer.getLABVector(im, 0, 0, cols, rows)
		
		# Store the Lab Vector into the Google Datastore
		ImageDatastore().set_Lab_vector(userId, photoId, labVec)
		
		# Prepare JSON response
		json_response = json.dumps( {"success": True, "photoId": photoId}, indent=4)
		
		# Write JSON response
		self.response.headers['Content-Type'] = 'application/json'
		self.response.write(json_response)
コード例 #14
0
    def snapShotterDidCaptureImage(self, snapShotter, imagePath):
        # the first image is ignored, as it is very different form the second
        # one, even when no change in the scene is present. (Maybe the PiCam
        # still has to focus or adjust light settings).
        if not self._hasIgnoredFirstImage:
            self._hasIgnoredFirstImage = True
            os.remove(imagePath)
            return

        if self._imageAnalyzer == None:
            self._imageAnalyzer = ImageAnalyzer(initialImagePath = imagePath)
        else:
            analysisResult = self._imageAnalyzer.compareNextImage(
                imagePath)
            if analysisResult != None:
                (differentPixelCount,
                    totalSquaredDifference,
                    totalNumberOfPixels) = analysisResult
                self.analyzeNewImageResult(
                    differentPixelCount,
                    totalSquaredDifference)

        os.remove(imagePath)
コード例 #15
0
class TargetDetection:
    def __init__(self, store_pics=False):
        self.cam = picamera.PiCamera()
        self.cam.resolution = (resolution['x'], resolution['y'])
        self.analyzer = ImageAnalyzer(adaptive_threshold=True)
        self.logger = Log.instance('TargetDetection')
        self.store_pics = store_pics

        if os.path.exists(dir_name):
            shutil.rmtree(dir_name)
        os.makedirs(dir_name)

    def distance_to_target(self):
        start = time.process_time()
        pic = np.empty((resolution['y'], resolution['x'], 3), dtype=np.uint8)
        self.cam.capture(pic, 'bgr')
        if self.store_pics:
            save_start = time.process_time()
            save_to = os.path.join(dir_name, str(int(time.time())) + '.jpg')
            self.logger.debug('save to: {}'.format(save_to))
            cv2.imwrite(save_to, pic)
            self.logger.debug('stored picture at "{}"'.format(save_to))
            save_end = time.process_time()
            self.logger.info('{:4d}ms to save image'.format(
                int((save_end - save_start) * 1000)))
        try:
            px, mm = self.analyzer.calculate_distance(pic)
            end = time.process_time()
            diff = int((end - start) * 1000)
            msg = 'distance: {:4d}px\t{:3.0f}mm\t{:4d}ms'.format(px, mm, diff)
            self.logger.info(msg)
            return mm
        except Exception as e:
            end = time.process_time()
            self.logger.info('{:4d}ms, no distance detected'.format(
                int((end - start) * 1000)))
            self.logger.error(e)
コード例 #16
0
import os

from ImageAnalyzer import ImageAnalyzer
from plate_recognition_service.PlateRecognitionService import PlateRecognitionService

if __name__ == "__main__":
    character_recognition_model_path = f'{os.getcwd()}/models/svc/svc.pkl'

    image_analyzer = ImageAnalyzer(character_recognition_model_path,
                                   0.4,
                                   reset_between_predictions=True)
    service = PlateRecognitionService(image_analyzer).start(port=5000)
コード例 #17
0
# getting the current directory and setting it to the folder with images
scripts_directory = os.getcwd()
ir_images_directory = scripts_directory.replace("/scripts", "/images/IR")
regular_images_directory = scripts_directory.replace("/scripts",
                                                     "/images/Regular")
reports_directory = scripts_directory.replace("/scripts", "/reports")

outfile = open(reports_directory + "/ir_images.csv", 'w')

# looping through every image in the folder containing IR images
for root, dirs, files in os.walk(ir_images_directory):
    for f in files:
        #counter+=1
        if (f[-3:].lower() == "jpg"):
            #if (f[-3:].lower() == "jpg" and counter % 10  == 0):   # only detects the file if it is a .jpg
            temp_analyzer = ImageAnalyzer(root + "/" + f)
            image_number_ir.append(counter)
            image_width = temp_analyzer.getImageWidth()
            image_height = temp_analyzer.getImageHeight()
            temp_analyzer.cropImage(int((7 / 16.0) * image_width),
                                    int((7 / 16.0) * image_height),
                                    int((9 / 16.0) * image_width),
                                    int((9 / 16.0) * image_height))
            ir_brightness.append(temp_analyzer.getImageHls()[1])
            #outfile.write(str(counter) + "," + str(temp_analyzer.getImageHls()[1]) + "\n")
            counter += 1
            print(
                str(counter) + "   " + root + "/" + f + "         " +
                str(temp_analyzer.getImageHls()[1]))

counter = 0
コード例 #18
0
class MotionDetector():
    _hasIgnoredFirstImage = False
    _snapShotter = None
    _isDetecting = False
    _imageAnalyzer = None
    _previousPixelCounts = []
    _previousSquaredDifference = []
    numberOfImagesToAverage = 3
    motionDetectorHandler = None

    # PiCameraSnapShotter callbacks
    def snapShotterFileNameForCapture(self):
        fileName = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
        fileName = "%s.bmp" % fileName
        return fileName

    def snapShotterDidCaptureImage(self, snapShotter, imagePath):
        # the first image is ignored, as it is very different form the second
        # one, even when no change in the scene is present. (Maybe the PiCam
        # still has to focus or adjust light settings).
        if not self._hasIgnoredFirstImage:
            self._hasIgnoredFirstImage = True
            os.remove(imagePath)
            return

        if self._imageAnalyzer == None:
            self._imageAnalyzer = ImageAnalyzer(initialImagePath = imagePath)
        else:
            analysisResult = self._imageAnalyzer.compareNextImage(
                imagePath)
            if analysisResult != None:
                (differentPixelCount,
                    totalSquaredDifference,
                    totalNumberOfPixels) = analysisResult
                self.analyzeNewImageResult(
                    differentPixelCount,
                    totalSquaredDifference)

        os.remove(imagePath)

    def analyzeNewImageResult(
        self,
        differentPixelCount,
        totalSquaredDifference):

        self._previousPixelCounts.append(differentPixelCount)
        self._previousSquaredDifference.append(totalSquaredDifference)

        if len(self._previousSquaredDifference) > self.numberOfImagesToAverage:
            self._previousSquaredDifference.pop(0)
            self._previousPixelCounts.pop(0)

        if len(self._previousPixelCounts) == self.numberOfImagesToAverage:
            pixelSum = sum(self._previousSquaredDifference)
            pixelLength = len(self._previousSquaredDifference)
            averagePixelDifference = pixelSum / float(pixelLength)

            differenceSum = sum(self._previousPixelCounts)
            differenceLength = len(self._previousPixelCounts)
            averagePixelCount = differenceSum / float(differenceLength)

            pixels = abs(differentPixelCount - averagePixelCount)
            squaredDelta = None
            if abs(averagePixelDifference) > 0:
                squaredDelta = abs(totalSquaredDifference / averagePixelDifference)

            # these are some of the values that can be tweaked for
            # a better detection experience (maybe a true)
            if squaredDelta > 1.1 and pixels > 10:
                if self.motionDetectorHandler is None:
                    timestamp = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
                    print "%s - Motion detected, but there is no handler." %timestamp
                else:
                    self.motionDetectorHandler.motionDetectorDetectedMotion(self)

    def startDetecting(self):
        if self._isDetecting == False:
            self._isDetecting = True
            thread = Thread(target = self._startDetectingOnThread)
            thread.start()
        else:
            print "Already detecting, ignoring call to startDetecting()"

    def _startDetectingOnThread(self):
        if self._snapShotter == None:
            snapShotter = PiCameraSnapshotter(repeats = True, interval = 1.0)
            snapShotter.delegate = self

        snapShotter.startSnapShotting()
        while self._isDetecting == True:
            time.sleep(1)

        snapShotter.stopSnapShotting()

    def stopDetecting(self):
        if self._isDetecting == True:
            self._imageAnalyzer.cancel();
            self._isDetecting = False
        else:
            print "Not detecting, ignoring call to stopDetecting()"
コード例 #19
0
ファイル: main.py プロジェクト: sc99/GFAnalyzer
from ImageAnalyzer import ImageAnalyzer

imgAnalyzer = ImageAnalyzer('sample.png')
for c in imgAnalyzer.contourize():
    imgAnalyzer.analyzefigure(c)
コード例 #20
0
ir_images_directory = scripts_directory.replace("/scripts", "/images/ir_images")
#ir_images_directory = "/Users/stoudenmiersh/OneDrive/DCIM/IR_Photos"
reports_directory = scripts_directory.replace("/scripts", "/reports")

outfile = open(reports_directory + "/ir_images.csv", 'w')

# looping through every image in the folder containing the images
for root, dirs, files in os.walk(ir_images_directory):
    if(len(dirs) == 0):
        temp_path = root
    for root2, dirs2, files2 in os.walk(temp_path):
        for f in files2:
            #counter+=1
            if (f[-3:].lower() == "jpg"):
            #if (f[-3:].lower() == "jpg" and counter % 10  == 0):   # only detects the file if it is a .jpg
                temp_analyzer = ImageAnalyzer(root2+"/"+f)
                x_values.append(counter)
                image_width = temp_analyzer.getImageWidth()
                image_height = temp_analyzer.getImageHeight()
                temp_analyzer.cropImage(int((7/16.0)*image_width), 0,
                                        int((9/16.0)*image_width), int((1/8.0)*image_height))
                y_values.append(temp_analyzer.getImageHls()[1])
                outfile.write(str(counter) + "," + str(temp_analyzer.getImageHls()[1]) + "\n")
                counter+=1
                print(str(counter) + "   " + root2+"/"+f + "         "+str(temp_analyzer.getImageHls()[1]))

    #plt.plot(x_values,y_values)

# Use polyfit.
#best_fit = polyfit(x_values, y_values, 3)
#polynomial = poly1d(best_fit)
コード例 #21
0
class Photomosaic:
	# Variables
	total_rows = 0
	total_cols = 0
	progress = 0
	photoLog = []
	cellLog = []
	photos = {}
	subimage = {}
	
	# Convenience objects
	ImgAnalyzer = None
	ImgFinder = None
	ImgLoader = None

	# The input image to analyze
	input = None
	input_grid_width = 0
	input_grid_height = 0
	input_cell_width = 0
	input_cell_height = 0
	
	# The output photomosiac based on the input image
	output = None
	output_mag = 1
	output_grid_width = 0
	output_grid_height = 0
	output_cell_width = 0
	output_cell_height = 0
	
	# Constructor
	def __init__(self, input_PIL_img, lib_Lab_vectors, photoLog, cellLog, subimage, progress=0):
		# Set instance variables
		self.input = input_PIL_img
		self.photoLog = photoLog # The photoLog, cellLog, and progress should probably be in it's own information expert
		self.cellLog = cellLog
		self.progress = int(progress)
		self.ImgAnalyzer = ImageAnalyzer()
		self.ImgFinder = ImageFinder(lib_Lab_vectors)
		self.ImgLoader = ImageLoader()
		self.subimage = subimage
		
	# Calculate all of the closests photos in the photomosaic
	def calculate_photomosaic(self, rows, cols):
		# Initialize input image
		self._input_dims(int(rows), int(cols))
		
		# Find the initial coordinates
		row = int(len(self.cellLog) / self.total_cols)
		col = int(len(self.cellLog) % self.total_cols)
		x0 = col*self.input_cell_width
		y0 = row*self.input_cell_height
		
		# Traverse the cells, and call "_process_cell" for each one of them
		self._traverse_cells(self._process_cell, x0, y0)
		
	# Create the photomosiac - currently only works with a square (rows=cols)
	def create_photomosaic(self, rows, cols, mag):
		# Initialize input and output images
		self._input_dims(int(rows), int(cols))
		self._output_dims(float(mag))
		
		# Find the initial coordinates to start pasting cells
		row = int(self.progress / self.total_cols)
		col = int(self.progress % self.total_cols)
		x0 = col*self.input_cell_width
		y0 = row*self.input_cell_height
		
		# Traverse the cells, and call "_paste_cell" for each one of them
		self._traverse_cells(self._paste_cell, x0, y0)
		
		# Return the ouput image as a base64 encoded string
		return self.base64()
		
	# Return the output image as a base64 encoded string
	def base64(self):
		file = StringIO()
		self.output.save(file, "png")
		return b64encode(file.getvalue())
		
	# Traverse the cells
	def _traverse_cells(self, fnc_process_cell, x0=0, y0=0):
		for y in range(y0, self.input_grid_height, self.input_cell_height):
			if y != y0: x0 = 0 # Only start in the middle of the grid on the first iteration
			for x in range(x0, self.input_grid_width, self.input_cell_width):
				fnc_process_cell(x, y)
				self.progress += 1

	# Analyze the input cell, find the best match, and add it to the cell log
	def _process_cell(self, x0, y0):
		labVec = self.ImgAnalyzer.getLABVector(self.input, x0, y0, self.input_cell_width, self.input_cell_height)
		closest_photoId = self.ImgFinder.closest_match(labVec)
		self.cellLog.append(closest_photoId)
		
	# Download the image and paste it into the output image
	def _paste_cell(self, x0, y0):
		# Translate the x and y coordinates into a cellLog index and find the photoId
		row = int(y0/self.input_cell_height)
		col = int(x0/self.input_cell_width)
		cellLogIndex = row*self.total_cols + col
		photoId = self.cellLog[cellLogIndex]
		
		# Get the image associated with the photo
		if photoId in self.photos:
			# We already have the image, so grab it from the dictionary
			closest_img = self.photos[photoId]
		else:
			# We haven't previously downloaded the image, so get it from Facebook
			closest_img = self.ImgLoader.load_url_image(self._get_url(photoId))
			
			# Crop the image and resize it into a square
			closest_img = self._crop_resize_square(closest_img)
			
			# Add the image to the photos dictionary
			self.photos[photoId] = closest_img
		
		# Now that the image has been found, paste it into the corresponding output cell
		self.output.paste( closest_img, (col*self.output_cell_width, row*self.output_cell_height) )
		
	# Returns the URL associated with the photoId
	def _get_url(self, photoId):
		for log in self.photoLog:
			if log["photoId"] == photoId:
				return log["url"]
		else: return None
		
	# Crop the image into a square and resize it to the output cell size
	def _crop_resize_square(self, im):
		cols, rows = im.size
		
		# Landscape Layout (or Square)
		if cols >= rows:
			target_cols = rows
			left = (cols-target_cols)/2
			right = left+target_cols
			return im.transform( (self.output_cell_width, self.output_cell_height), Image.EXTENT, (left, 0, right, rows) )
			
		# Portrait Layout
		else:
			target_rows = cols
			upper = (rows-target_rows)/2
			lower = upper+target_rows
			return im.transform( (self.output_cell_width, self.output_cell_height), Image.EXTENT, (0, upper, cols, lower) )

	# Defines input dimensions
	def _input_dims(self, rows, cols):
		# Since number of columns is the width and number of rows is height
		self.input_grid_width  = self.subimage["w"]
		self.input_grid_height = self.subimage["h"]
	
		self.total_rows = int(rows)
		self.total_cols = int(cols)
		
		self.input_grid_width  -= self.input_grid_width  % self.total_cols
		self.input_grid_height -= self.input_grid_height % self.total_rows
		
		self.input_cell_width  = self.input_grid_width  / self.total_cols
		self.input_cell_height = self.input_grid_height / self.total_rows
		
		# Crop Image
		self.input = self.input.crop( (self.subimage["x"], self.subimage["y"], self.subimage["x"]+self.input_cell_width*self.total_cols, self.subimage["y"]+self.input_cell_height*self.total_rows) )


	# Defines output dimensions and creates output image
	def _output_dims(self, mag):
		# Set dimensions
		self.output_mag = float(mag)
		self.output_grid_width  = int(self.input_grid_width  * self.output_mag)
		self.output_grid_height = int(self.input_grid_height * self.output_mag)
		
		self.output_grid_width  -= self.output_grid_width  % self.total_cols
		self.output_grid_height -= self.output_grid_height % self.total_rows
		
		self.output_cell_width  = self.output_grid_width  / self.total_cols
		self.output_cell_height = self.output_grid_height / self.total_rows
		
		# Create output image
		self.output = Image.new("RGB", (self.output_grid_width, self.output_grid_height), "red")