Пример #1
0
def getArchivedImages(constants, cameras, startTimeDT, timeRangeSeconds,
                      minusMinutes):
    """Get random images from HPWREN archive matching given constraints and optionally subtract them

    Args:
        constants (dict): "global" contants
        cameras (list): list of cameras
        startTimeDT (datetime): starting time of time range
        timeRangeSeconds (int): number of seconds in time range
        minusMinutes (int): number of desired minutes between images to subract

    Returns:
        Tuple containing camera name, current timestamp, filepath of regular image, and filepath of difference image
    """
    if getArchivedImages.tmpDir == None:
        getArchivedImages.tmpDir = tempfile.TemporaryDirectory()
        logging.warning('TempDir %s', getArchivedImages.tmpDir.name)

    cameraID = cameras[int(len(cameras) * random.random())]['name']
    timeDT = startTimeDT + datetime.timedelta(seconds=random.random() *
                                              timeRangeSeconds)
    if minusMinutes:
        prevTimeDT = timeDT + datetime.timedelta(seconds=-60 * minusMinutes)
    else:
        prevTimeDT = timeDT
    files = img_archive.getHpwrenImages(constants['googleServices'], settings,
                                        getArchivedImages.tmpDir.name,
                                        constants['camArchives'], cameraID,
                                        prevTimeDT, timeDT, minusMinutes or 1)
    # logging.warning('files %s', str(files))
    if not files:
        return (None, None, None, None)
    if minusMinutes:
        if len(files) > 1:
            if files[0] >= files[
                    1]:  # files[0] is supposed to be earlier than files[1]
                logging.warning('unexpected file order %s', str(files))
                for file in files:
                    os.remove(file)
                return (None, None, None, None)
            imgDiffPath = genDiffImage(files[1], files[0], minusMinutes)
            os.remove(files[0])  # no longer needed
            parsedName = img_archive.parseFilename(files[1])
            return (cameraID, parsedName['unixTime'], files[1], imgDiffPath)
        else:
            logging.warning('unexpected file count %s', str(files))
            for file in files:
                os.remove(file)
            return (None, None, None, None)
    elif len(files) > 0:
        parsedName = img_archive.parseFilename(files[0])
        return (cameraID, parsedName['unixTime'], files[0], files[0])
    return (None, None, None, None)
Пример #2
0
def getNextImageFromDir(imgDirectory):
    """Gets the next image to check for smoke from given directory

    A variant of getNextImage() above but works with files already present
    on the locla filesystem.

    Args:
        imgDirectory (str): directory containing the files

    Returns:
        Tuple containing camera name, current timestamp, and filepath of the image
    """
    if getNextImageFromDir.tmpDir == None:
        getNextImageFromDir.tmpDir = tempfile.TemporaryDirectory()
        logging.warning('TempDir %s', getNextImageFromDir.tmpDir.name)
    if not getNextImageFromDir.files:
        allFiles = os.listdir(imgDirectory)
        # filter out files with _Score suffix because they contain annotated scores
        # generated by drawFireBox() function below.
        getNextImageFromDir.files = list(
            filter(lambda x: '_Score.jpg' not in x, allFiles))
    getNextImageFromDir.index += 1
    if getNextImageFromDir.index < len(getNextImageFromDir.files):
        fileName = getNextImageFromDir.files[getNextImageFromDir.index]
        origPath = os.path.join(imgDirectory, fileName)
        destPath = os.path.join(getNextImageFromDir.tmpDir.name, fileName)
        shutil.copyfile(origPath, destPath)
        parsed = img_archive.parseFilename(fileName)
        if not parsed:
            # failed to parse, so skip to next image
            return getNextImageFromDir(imgDirectory)
        md5 = hashlib.md5(open(destPath, 'rb').read()).hexdigest()
        return (parsed['cameraID'], parsed['unixTime'], destPath, md5)
    logging.warning('Finished processing all images in directory. Exiting')
    exit(0)
Пример #3
0
def downloadClassImage(service, classLocations, imgClass, fileName, outputDirectory):
    """Download image file with given name from given image class from Fuego Cropping/Pictures/<imgClass> folder

    Args:
        service: Drive service (from getGoogleServices()['drive'])
        classLocations (dict): Dict of immgClass -> drive folder ID
        imgClass (str): image class (smoke, nonSmoke, etc..)
        fileName (str): Name of image file
        outputDirectory (str): Local directory where to store the file

    Returns:
        Local file system path to downloaded file
    """
    localFilePath = os.path.join(outputDirectory, fileName)
    if os.path.isfile(localFilePath):
        return localFilePath # already downloaded, nothing to do

    # parse cameraID from fileName
    parsed = img_archive.parseFilename(fileName)
    cameraID = parsed['cameraID']

    # find subdir for camera
    (dirID, dirName) = getDirForClassCamera(service, classLocations, imgClass, cameraID)

    # find file in camera subdir
    downloadFile(service, dirID, fileName, localFilePath)
    return localFilePath
Пример #4
0
def getCameraDir(service, cameraCache, fileName):
    parsed = img_archive.parseFilename(fileName)
    cameraID = parsed['cameraID']
    dirID = cameraCache.get(cameraID)
    if not dirID:
        (dirID, dirName) = goog_helper.getDirForClassCamera(service, settings.IMG_CLASSES, 'smoke', cameraID)
        cameraCache[cameraID] = dirID
    return dirID
Пример #5
0
def capture_and_record(googleServices, dbManager, outputDir, camera_name):
    """requests current image from camera and uploads it to cloud
    Args:
        googleServices: Drive service (from getGoogleServices())
        outputDir (str): folder path to download into
        camera_name (str): name of camera as recorded by alertwildfire
    Returns:
        imgPath: local path to downloaded object
    """
    success = False
    retriesLeft = 5
    pull1 = alertwildfire_API.get_individual_camera_info(camera_name)
    while (not success) and (retriesLeft > 0):

        imgPath = alertwildfire_API.request_current_image(
            outputDir, camera_name)
        pull2 = alertwildfire_API.get_individual_camera_info(camera_name)
        if pull1['position'] == pull1['position']:
            success = True
        else:
            pull1 = pull2
            retriesLeft -= 1
    #validate that it is new data
    md5 = hashlib.md5(open(imgPath, 'rb').read()).hexdigest()
    ###warning approximitly doubles image processing time
    #SQLcommand="select FileID from archive where md5='"+str(md5)+"'"
    #matches = dbManager.query(SQLcommand)
    #if len(matches)>0:
    #    logging.warning('skipping %s, image has not changed since last upload.', camera_name)
    #    return
    ###

    image_base_name = pathlib.PurePath(imgPath).name
    image_name_with_metadata = build_name_with_metadata(image_base_name, pull1)
    cloud_file_path = 'alert_archive/' + camera_name + '/' + image_name_with_metadata
    goog_helper.uploadBucketObject(googleServices["storage"],
                                   settings.archive_storage_bucket,
                                   cloud_file_path, imgPath)

    #add to Database
    timeStamp = img_archive.parseFilename(image_base_name)['unixTime']
    img_archive.addImageToArchiveDb(dbManager, camera_name, timeStamp,
                                    'gs://' + settings.archive_storage_bucket,
                                    cloud_file_path, pull1['position']['pan'],
                                    pull1['position']['tilt'],
                                    pull1['position']['zoom'], md5)
Пример #6
0
def genDiffImage(imgPath, earlierImgPath, minusMinutes):
    """Subtract the two given images and store result in new difference image file

    Args:
        imgPath (str): filepath of the current image (to subtract from)
        imgPath (str): filepath of the earlier image (value to subtract)
        minusMinutes (int): number of minutes separating subtracted images

    Returns:
        file path to the difference image
    """
    imgA = Image.open(imgPath)
    imgB = Image.open(earlierImgPath)
    imgDiff = img_archive.diffImages(imgA, imgB)
    parsedName = img_archive.parseFilename(imgPath)
    parsedName['diffMinutes'] = minusMinutes
    imgDiffName = img_archive.repackFileName(parsedName)
    ppath = pathlib.PurePath(imgPath)
    imgDiffPath = os.path.join(str(ppath.parent), imgDiffName)
    imgDiff.save(imgDiffPath, format='JPEG')
    return imgDiffPath
Пример #7
0
def getTimeFromName(imgName):
    return img_archive.parseFilename(imgName)
Пример #8
0
def image_library(input_csv):
    cropped_image_list = np.loadtxt(input_csv, delimiter = ',', dtype = str)
    image_name_list = []
    for image_name in cropped_image_list:
        image_name_list += [parseFilename(image_name[0])]
    return cropped_image_list, image_name_list
Пример #9
0
def main():
    reqArgs = [
        ["o", "outputDir", "local directory to save diff image segments"],
        ["i", "inputDir", "input local directory containing nonSmoke image segments"],
        ["m", "minusMinutes", "subtract images from given number of minutes ago"],
    ]
    optArgs = [
        ["s", "startRow", "starting row"],
        ["e", "endRow", "ending row"],
    ]
    args = collect_args.collectArgs(reqArgs, optionalArgs=optArgs, parentParsers=[goog_helper.getParentParser()])
    minusMinutes = int(args.minusMinutes)
    startRow = int(args.startRow) if args.startRow else 0
    endRow = int(args.endRow) if args.endRow else 1e9

    googleServices = goog_helper.getGoogleServices(settings, args)
    cookieJar = None
    camArchives = None
    cookieJar = img_archive.loginAjax()
    camArchives = img_archive.getHpwrenCameraArchives(googleServices['sheet'], settings)
    timeGapDelta = datetime.timedelta(seconds = 60*minusMinutes)
    skippedBadParse = []
    skippedArchive = []
    imageFileNames = sorted(os.listdir(args.inputDir))
    rowIndex = -1
    for fileName in imageFileNames:
        rowIndex += 1

        if rowIndex < startRow:
            continue
        if rowIndex > endRow:
            print('Reached end row', rowIndex, endRow)
            break

        if (fileName[:3] == 'v2_') or (fileName[:3] == 'v3_'):
            continue # skip replicated files
        logging.warning('Processing row %d, file: %s', rowIndex, fileName)
        parsedName = img_archive.parseFilename(fileName)

        if (not parsedName) or parsedName['diffMinutes'] or ('minX' not in parsedName):
            logging.warning('Skipping file with unexpected parsed data: %s, %s', fileName, str(parsedName))
            skippedBadParse.append((rowIndex, fileName, parsedName))
            continue # skip files without crop info or with diff
        matchingCams = list(filter(lambda x: parsedName['cameraID'] == x['id'], camArchives))
        if len(matchingCams) != 1:
            logging.warning('Skipping camera without archive: %d, %s', len(matchingCams), str(matchingCams))
            skippedArchive.append((rowIndex, fileName, matchingCams))
            continue
        archiveDirs = matchingCams[0]['dirs']
        logging.warning('Found %s directories', archiveDirs)
        earlierImgPath = None
        dt = datetime.datetime.fromtimestamp(parsedName['unixTime'])
        dt -= timeGapDelta
        for dirName in archiveDirs:
            logging.warning('Searching for files in dir %s', dirName)
            imgPaths = img_archive.getFilesAjax(cookieJar, settings.downloadDir, parsedName['cameraID'], dirName, dt, dt, 1)
            if imgPaths:
                earlierImgPath = imgPaths[0]
                break # done
        if not earlierImgPath:
            logging.warning('Skipping image without prior image: %s, %s', str(dt), fileName)
            skippedArchive.append((rowIndex, fileName, dt))
            continue
        logging.warning('Subtracting old image %s', earlierImgPath)
        earlierImg = Image.open(earlierImgPath)
        print('CR', (parsedName['minX'], parsedName['minY'], parsedName['maxX'], parsedName['maxY']))
        croppedEarlyImg = earlierImg.crop((parsedName['minX'], parsedName['minY'], parsedName['maxX'], parsedName['maxY']))

        imgOrig = Image.open(os.path.join(args.inputDir, fileName))
        diffImg = img_archive.diffImages(imgOrig, croppedEarlyImg)
        parsedName['diffMinutes'] = minusMinutes
        diffImgPath = os.path.join(args.outputDir, img_archive.repackFileName(parsedName))
        logging.warning('Saving new image %s', diffImgPath)
        diffImg.save(diffImgPath, format='JPEG')
    logging.warning('Skipped bad parse %d, %s', len(skippedBadParse), str(skippedBadParse))
    logging.warning('Skipped images without archives %d, %s', len(skippedArchive), str(skippedArchive))
Пример #10
0
def main():
    reqArgs = [
        ["o", "outputDir", "local directory to save images segments"],
        ["i", "inputCsv", "csvfile with contents of Fuego Cropped Images"],
    ]
    optArgs = [
        ["s", "startRow", "starting row"],
        ["e", "endRow", "ending row"],
        ["d", "display", "(optional) specify any value to display image and boxes"],
        ["x", "minDiffX", "(optional) override default minDiffX of 299"],
        ["y", "minDiffY", "(optional) override default minDiffY of 299"],
        ["a", "minArea", "(optional) override default throw away areas < 1/100 of 299x299"],
        ["t", "throwSize", "(optional) override default throw away size of 1000x1000"],
        ["g", "growRatio", "(optional) override default grow ratio of 1.2"],
        ["m", "minusMinutes", "(optional) subtract images from given number of minutes ago"],
    ]
    args = collect_args.collectArgs(reqArgs, optionalArgs=optArgs, parentParsers=[goog_helper.getParentParser()])
    startRow = int(args.startRow) if args.startRow else 0
    endRow = int(args.endRow) if args.endRow else 1e9
    minDiffX = int(args.minDiffX) if args.minDiffX else 299
    minDiffY = int(args.minDiffY) if args.minDiffY else 299
    throwSize = int(args.throwSize) if args.throwSize else 1000
    growRatio = float(args.growRatio) if args.growRatio else 1.2
    minArea = int(args.minArea) if args.minArea else int(299*2.99)
    minusMinutes = int(args.minusMinutes) if args.minusMinutes else 0

    googleServices = goog_helper.getGoogleServices(settings, args)
    camArchives = img_archive.getHpwrenCameraArchives(googleServices['sheet'], settings)
    if minusMinutes:
        timeGapDelta = datetime.timedelta(seconds = 60*minusMinutes)
    cameraCache = {}
    skippedTiny = []
    skippedHuge = []
    skippedArchive = []
    with open(args.inputCsv) as csvFile:
        csvreader = csv.reader(csvFile)
        for (rowIndex, csvRow) in enumerate(csvreader):
            if rowIndex < startRow:
                continue
            if rowIndex > endRow:
                print('Reached end row', rowIndex, endRow)
                break
            [cropName, minX, minY, maxX, maxY, fileName] = csvRow[:6]
            minX = int(minX)
            minY = int(minY)
            maxX = int(maxX)
            maxY = int(maxY)
            oldCoords = (minX, minY, maxX, maxY)
            if ((maxX - minX) > throwSize) and ((maxY - minY) > throwSize):
                logging.warning('Skip large image: dx=%d, dy=%d, name=%s', maxX - minX, maxY - minY, fileName)
                skippedHuge.append((rowIndex, fileName, maxX - minX, maxY - minY))
                continue
            if ((maxX - minX) * (maxY - minY)) < minArea:
                logging.warning('Skipping tiny image with area: %d, name=%s', (maxX - minX) * (maxY - minY), fileName)
                skippedTiny.append((rowIndex, fileName, (maxX - minX) * (maxY - minY)))
                continue
            # get base image from google drive that was uploaded by sort_images.py

            dirID = getCameraDir(googleServices['drive'], cameraCache, fileName)#-##REPLACE DEP. GDRIVE W HPREWN#
            localFilePath = os.path.join(settings.downloadDir, fileName)#sets a path for that image() not yet downloadedby this iteration
            print('local', localFilePath)
            if not os.path.isfile(localFilePath):# if file has not been downloaded by a previous iteration
                print('download', fileName)
                #+##REPLACE DEP. GDRIVE W HPREWN#nameParsed = img_archive.parseFilename(fileName)#parses file name into dictionary of parts name,unixtime,etc.
                #+##REPLACE DEP. GDRIVE W HPREWN#matchingCams = list(filter(lambda x: nameParsed['cameraID'] == x['id'], camArchives))#filter through camArchives for ids matching cameraid
                #+##REPLACE DEP. GDRIVE W HPREWN#if len(matchingCams) != 1:#if we cannot determine where the image will come from we cannot use the image
                #+##REPLACE DEP. GDRIVE W HPREWN#    logging.warning('Skipping camera without archive: %d, %s', len(matchingCams), str(matchingCams))
                #+##REPLACE DEP. GDRIVE W HPREWN#    skippedArchive.append((rowIndex, fileName, matchingCams))
                #+##REPLACE DEP. GDRIVE W HPREWN#    continue
                #+##REPLACE DEP. GDRIVE W HPREWN#archiveDirs = matchingCams[0]['dirs']
                #+##REPLACE DEP. GDRIVE W HPREWN#logging.warning('Found %s directories', archiveDirs)
                #+##REPLACE DEP. GDRIVE W HPREWN#time = datetime.datetime.fromtimestamp(nameParsed['unixTime'])
                #+##REPLACE DEP. GDRIVE W HPREWN#for dirName in archiveDirs:#search directories of camera for a time near
                #+##REPLACE DEP. GDRIVE W HPREWN#    logging.warning('Searching for files in dir %s', dirName)
                #+##REPLACE DEP. GDRIVE W HPREWN#    imgPaths = img_archive.downloadFilesHpwren(settings.downloadDir, nameParsed['cameraID'], dirName, time, time, 1, 0)
                #+##REPLACE DEP. GDRIVE W HPREWN#    if imgPaths:
                #+##REPLACE DEP. GDRIVE W HPREWN#        localFilePath = imgPaths[0]
                #+##REPLACE DEP. GDRIVE W HPREWN#        break
                #+##REPLACE DEP. GDRIVE W HPREWN#if not imgPaths:
                #+##REPLACE DEP. GDRIVE W HPREWN#    logging.warning('Skipping image not found: %s', fileName)
                #+##REPLACE DEP. GDRIVE W HPREWN#    skippedArchive.append((rowIndex, fileName, time))#archive that images were skipped
                #+##REPLACE DEP. GDRIVE W HPREWN#    continue
                goog_helper.downloadFile(googleServices['drive'], dirID, fileName, localFilePath)#-##REPLACE DEP. GDRIVE W HPREWN#
            imgOrig = Image.open(localFilePath)#opens image

            # if in subracted images mode, download an earlier image and subtract
            if minusMinutes:
                nameParsed = img_archive.parseFilename(fileName)#parses file name into dictionary of parts name,unixtime,etc.
                dt = datetime.datetime.fromtimestamp(nameParsed['unixTime'])
                dt -= timeGapDelta
                earlierImgPath = None
                files = img_archive.getHpwrenImages(googleServices, settings, settings.downloadDir, camArchives, nameParsed['cameraID'], dt, dt, 1)
                if files:
                    earlierImgPath = files[0]
                else:
                    logging.warning('Skipping image without prior image: %s, %s', str(dt), fileName)
                    skippedArchive.append((rowIndex, fileName, dt))
                    continue
                logging.warning('Subtracting old image %s', earlierImgPath)
                earlierImg = Image.open(earlierImgPath)
                diffImg = img_archive.diffImages(imgOrig, earlierImg)
                # realImgOrig = imgOrig # is this useful?
                imgOrig = diffImg
                fileNameParts = os.path.splitext(fileName)
                fileName = str(fileNameParts[0]) + ('_Diff%d' % minusMinutes) + fileNameParts[1]

            # crop the full sized image to show just the smoke, but shifted and flipped
            # shifts and flips increase number of segments for training and also prevent overfitting by perturbing data
            cropCoords = getCropCoords((minX, minY, maxX, maxY), minDiffX, minDiffY, growRatio, (imgOrig.size[0], imgOrig.size[1]))
            for newCoords in cropCoords:
                # XXXX - save work if old=new?
                print('coords old,new', oldCoords, newCoords)
                imgNameNoExt = str(os.path.splitext(fileName)[0])
                cropImgName = imgNameNoExt + '_Crop_' + 'x'.join(list(map(lambda x: str(x), newCoords))) + '.jpg'
                cropImgPath = os.path.join(args.outputDir, cropImgName)
                cropped_img = imgOrig.crop(newCoords)
                cropped_img.save(cropImgPath, format='JPEG')
                flipped_img = cropped_img.transpose(Image.FLIP_LEFT_RIGHT)
                flipImgName = imgNameNoExt + '_Crop_' + 'x'.join(list(map(lambda x: str(x), newCoords))) + '_Flip.jpg'
                flipImgPath = os.path.join(args.outputDir, flipImgName)
                flipped_img.save(flipImgPath, format='JPEG')
            print('Processed row: %s, file: %s' % (rowIndex, fileName))
            if args.display:
                displayCoords = [oldCoords] + cropCoords
                displayImageWithScores(imgOrig, displayCoords)
                imageDisplay(imgOrig)
    logging.warning('Skipped tiny images %d, %s', len(skippedTiny), str(skippedTiny))
    logging.warning('Skipped huge images %d, %s', len(skippedHuge), str(skippedHuge))
    logging.warning('Skipped images without archives %d, %s', len(skippedArchive), str(skippedArchive))