Skip to content

Commit

Permalink
Merge pull request #12 from MarkMichon1/staging
Browse files Browse the repository at this point in the history
merge staging to master
  • Loading branch information
MarkMichon1 authored Jun 6, 2019
2 parents 436315c + bb08d33 commit 82e0200
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 63 deletions.
17 changes: 10 additions & 7 deletions bitglitter/read/decoder.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import logging

from PIL import Image

from bitglitter.palettes.paletteutilities import paletteGrabber, ColorsToValue, _validateAndAddPalette
from bitglitter.read.decoderassets import minimumBlockCheckpoint, readFrameHeader, readInitializer, validatePayload
from bitglitter.read.framehandler import FrameHandler
Expand All @@ -21,6 +19,8 @@ def __init__(self, isVideo, configObject, scryptN, scryptR, scryptP, blockHeight
self.isVideo = isVideo
self.frameNumberofVideo = 0
self.activeFrame = None
self.frameHeight = None
self.frameWidth = None
self.checkpointPassed = True
self.fatalCheckpoint = True # Non-recoverable errors that require an immediate break from the loop.
self.streamHeaderCleared = False
Expand Down Expand Up @@ -75,7 +75,8 @@ def __init__(self, isVideo, configObject, scryptN, scryptR, scryptP, blockHeight
def decodeImage(self, fileToInput):
'''This method is used to decode a single image (jpg, png, bmp).'''

self.activeFrame = Image.open(fileToInput)
self.activeFrame = fileToInput
self.frameHeight, self.frameWidth, unused = self.activeFrame.shape
self.frameHandler.loadNewFrame(self.activeFrame, True)

if self._firstFrameSetup() == False:
Expand All @@ -95,7 +96,7 @@ def decodeImage(self, fileToInput):
self._attemptStreamPaletteLoad()


def decodeVideoFrame(self, fileToInput):
def decodeVideoFrame(self, activeFrame):
'''This is the higher level method that decodes and validates data from each video frame, and then passes it to
the Assembler object for further processing.
'''
Expand All @@ -107,7 +108,8 @@ def decodeVideoFrame(self, fileToInput):
self.carryOverBits = None
self.duplicateFrameRead = False

self.activeFrame = Image.open(fileToInput)
self.activeFrame = activeFrame
self.frameHeight, self.frameWidth, unused = self.activeFrame.shape

if self.frameNumberofVideo == 1:
self.frameHandler.loadNewFrame(self.activeFrame, True)
Expand Down Expand Up @@ -148,15 +150,16 @@ def _firstFrameSetup(self):
'''

self.checkpointPassed = minimumBlockCheckpoint(self.blockHeightOverride, self.blockWidthOverride,
self.activeFrame.size[0], self.activeFrame.size[1])
self.frameWidth, self.frameHeight)
if self.checkpointPassed == False:
return False

self.blockHeight = self.blockHeightOverride
self.blockWidth = self.blockWidthOverride

self.blockHeight, self.blockWidth, self.pixelWidth = frameLockOn(self.activeFrame, self.blockHeightOverride,
self.blockWidthOverride)
self.blockWidthOverride, self.frameWidth,
self.frameHeight)
if self.pixelWidth == False:
return False

Expand Down
24 changes: 8 additions & 16 deletions bitglitter/read/decoderassets.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import hashlib
import logging
import numpy
import zlib

from bitglitter.palettes.paletteutilities import paletteGrabber
Expand Down Expand Up @@ -40,22 +41,13 @@ def scanBlock(image, pixelWidth, blockWidthPosition, blockHeightPosition):
startPositionY = int(round((blockHeightPosition * pixelWidth) + (pixelWidth * .25), 1))
endPositionY = int(round(startPositionY + (pixelWidth * .5), 1))

scannedValues = []
pixel = image.load()
for xScan in range(endPositionX - startPositionX + 1):
for yScan in range(endPositionY - startPositionY + 1):
scannedValues.append(pixel[(startPositionX + xScan), (startPositionY + yScan)])

redChannel = 0
greenChannel = 0
blueChannel = 0
for value in scannedValues:
redChannel += value[0]
greenChannel += value[1]
blueChannel += value[2]

return (round(redChannel / len(scannedValues)), round(greenChannel / len(scannedValues)),
round(blueChannel / len(scannedValues)))
numpyOutput = numpy.flip(image[startPositionY:endPositionY, startPositionX:endPositionX]).mean(axis=(0,1))
toListFormat = numpyOutput.tolist()

for value in range(3):
toListFormat[value] = int(toListFormat[value])

return toListFormat


def readInitializer(bitStream, blockHeight, blockWidth, customPaletteList, defaultPaletteList):
Expand Down
13 changes: 6 additions & 7 deletions bitglitter/read/fileslicer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import os
import shutil

from cv2 import imread

from bitglitter.config.constants import VALID_VIDEO_FORMATS
from bitglitter.read.decoder import Decoder
Expand All @@ -17,9 +18,8 @@ def fileSlicer(fileToInput, activePath, outputPath, blockHeightOverride, blockWi
# Sets up workspace
readRoot = os.path.join(os.getcwd(), activePath)
workingFolder = readRoot + '\\Working Folder'
if os.path.isdir(workingFolder):
shutil.rmtree(workingFolder)
os.makedirs(workingFolder)
if not os.path.isdir(readRoot):
os.makedirs(readRoot)
configObject.assembler.workingFolder = readRoot

# Determines if the multimedia file is an image or a video.
Expand All @@ -37,7 +37,7 @@ def fileSlicer(fileToInput, activePath, outputPath, blockHeightOverride, blockWi
# lot of time attempting to read long videos with one failure after the next.
badFramesThisSession = 0

videoFramePuller = VideoFramePuller(fileToInput, workingFolder)
videoFramePuller = VideoFramePuller(fileToInput)

for frame in range(videoFramePuller.totalFrames):

Expand All @@ -58,7 +58,6 @@ def fileSlicer(fileToInput, activePath, outputPath, blockHeightOverride, blockWi
else:
logging.warning(f'Bad frame strike # {badFramesThisSession}')

videoFramePuller.removePreviousFrame()
configObject.saveSession()

else:
Expand All @@ -69,7 +68,7 @@ def fileSlicer(fileToInput, activePath, outputPath, blockHeightOverride, blockWi

else:
logging.info("Processing image...")
checkpointPassed = decoder.decodeImage(fileToInput)
checkpointPassed = decoder.decodeImage(imread(fileToInput))

if checkpointPassed == False:
logging.debug('Breaking out of fileSlicer(), checkpointPassed == False')
Expand Down
30 changes: 14 additions & 16 deletions bitglitter/read/framelockon.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import logging

from bitstring import BitArray, ConstBitStream
from numpy import flip

from bitglitter.read.coloranalysis import colorSnap, returnDistance
from bitglitter.read.decoderassets import scanBlock
from bitglitter.palettes.paletteutilities import paletteGrabber, ColorsToValue


def frameLockOn(image, blockHeightOverride, blockWidthOverride):
def frameLockOn(image, blockHeightOverride, blockWidthOverride, frameWidth, frameHeight):
'''This function is used to lock onto the frame. If override values are present, these will be used. Otherwise,
it will attempt to extract the correct values from the X and Y calibrator on the initial frame.'''

Expand All @@ -18,13 +19,10 @@ def frameLockOn(image, blockHeightOverride, blockWidthOverride):
initializerPaletteBDict = ColorsToValue(initializerPaletteB)
combinedColors = initializerPaletteA.colorSet + initializerPaletteB.colorSet

pixel = image.load()
imageWidth, imageHeight = image.size[0], image.size[1]

if blockHeightOverride and blockWidthOverride: # Jump straight to verification
logging.info("blockHeightOverride and blockWidthOverride parameters detected. Attempting to lock with these"
" values...")
pixelWidth = ((imageWidth / blockWidthOverride) + (imageHeight / blockHeightOverride)) / 2
pixelWidth = ((frameWidth / blockWidthOverride) + (frameHeight / blockHeightOverride)) / 2

checkpoint = verifyBlocksX(image, pixelWidth, blockWidthOverride, combinedColors, initializerPaletteADict,
initializerPaletteBDict, override=True)
Expand All @@ -40,23 +38,23 @@ def frameLockOn(image, blockHeightOverride, blockWidthOverride):

else:
# First checkpoint. Does pixel 0,0 have colorDistance value of under 100 for black (0,0,0)?
if returnDistance(pixel[0, 0], (0,0,0)) > 100:
if returnDistance(image[0, 0], (0,0,0)) > 100:
logging.warning('Frame lock fail! Initial pixel value exceeds maximum color distance allowed for a '
'reliable lock.')
return False, False, False

pixelWidth, blockDimensionGuess = pixelCreep(pixel, initializerPaletteA, initializerPaletteB, combinedColors,
initializerPaletteADict, initializerPaletteBDict, imageWidth,
imageHeight, width=True)
pixelWidth, blockDimensionGuess = pixelCreep(image, initializerPaletteA, initializerPaletteB, combinedColors,
initializerPaletteADict, initializerPaletteBDict, frameWidth,
frameHeight, width=True)
checkpoint = verifyBlocksX(image, pixelWidth, blockDimensionGuess, combinedColors, initializerPaletteADict,
initializerPaletteBDict)
if checkpoint == False:
return False, False, False

blockWidth = blockDimensionGuess
pixelWidth, blockDimensionGuess = pixelCreep(pixel, initializerPaletteA, initializerPaletteB, combinedColors,
initializerPaletteADict, initializerPaletteBDict, imageWidth,
imageHeight, width=False)
pixelWidth, blockDimensionGuess = pixelCreep(image, initializerPaletteA, initializerPaletteB, combinedColors,
initializerPaletteADict, initializerPaletteBDict, frameWidth,
frameHeight, width=False)
checkpoint = verifyBlocksY(image, pixelWidth, blockDimensionGuess, combinedColors, initializerPaletteADict,
initializerPaletteBDict)

Expand Down Expand Up @@ -148,7 +146,7 @@ def verifyBlocksY(image, pixelWidth, blockHeightEstimate, combinedColors, initia
return True


def pixelCreep(pixelObject, initializerPaletteA, initializerPaletteB, combinedColors, initializerPaletteADict,
def pixelCreep(image, initializerPaletteA, initializerPaletteB, combinedColors, initializerPaletteADict,
initializerPaletteBDict, imageWidth, imageHeight, width):
'''This function moves across the calibrator on the top and left of the frame one pixel at a time, and after
'snapping' the colors, decodes an unsigned integer from each axis, which if read correctly, is the block width and
Expand All @@ -173,15 +171,15 @@ def pixelCreep(pixelObject, initializerPaletteA, initializerPaletteB, combinedCo
for value in range(16):
while True:
if width == True:
axisOnImage = pixelOnDimension, 0
axisOnImage = 0, pixelOnDimension
axisAnalyzed = imageWidth

else:
axisOnImage = 0, pixelOnDimension
axisOnImage = pixelOnDimension, 0
axisAnalyzed = imageHeight

newPaletteLocked = False
activeScan = pixelObject[axisOnImage]
activeScan = flip(image[axisOnImage])
activeDistance = returnDistance(activeScan, activeColor)

pixelOnDimension += 1
Expand Down
22 changes: 5 additions & 17 deletions bitglitter/read/videoframepuller.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,22 @@
import logging
import os

import cv2


class VideoFramePuller:
'''This object is loads the BitGlitter-encoded video, and returns one frame at a time to be decoded.'''

def __init__(self, fileToInput, activePath):

self.activePath = activePath
def __init__(self, fileToInput):

self.activeVideo = cv2.VideoCapture(fileToInput)
logging.debug('Video successfully loaded into VideoFramePuller.')

self.currentFrame = 1
self.totalFrames = int(self.activeVideo.get(cv2.CAP_PROP_FRAME_COUNT))
logging.info(f'{self.totalFrames} frame(s) detected in video.')
self.currentFrame = 1


def nextFrame(self):
'''This method will automatically read the next frame from the video, and return the file path to that image.'''

self.image = self.activeVideo.read()
self.activeImagePath = f"{self.activePath}\\frame{self.currentFrame}.png"
cv2.imwrite(self.activeImagePath, self.image[1])
return self.activeImagePath


def removePreviousFrame(self):
'''After the frame is ran through the decoder, fileslicer will run this method to delete the frame.'''

os.remove(self.activeImagePath)
self.currentFrame += 1
self.currentFrame += 1
return self.activeVideo.read()[1]

0 comments on commit 82e0200

Please sign in to comment.