Пример #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 main():
    reqArgs = [
        ["c", "cameraID", "ID (code name) of camera"],
        [
            "s", "startTime",
            "starting date and time in ISO format (e.g., 2019-02-22T14:34:56 in Pacific time zone)"
        ],
    ]
    optArgs = [
        [
            "e", "endTime",
            "ending date and time in ISO format (e.g., 2019-02-22T14:34:56 in Pacific time zone)"
        ],
        [
            "g", "gapMinutes",
            "override default of 1 minute gap between images to download"
        ],
        ["o", "outputDir", "directory to save the output image"],
    ]

    args = collect_args.collectArgs(
        reqArgs,
        optionalArgs=optArgs,
        parentParsers=[goog_helper.getParentParser()])
    googleServices = goog_helper.getGoogleServices(settings, args)
    gapMinutes = int(args.gapMinutes) if args.gapMinutes else 1
    outputDir = args.outputDir if args.outputDir else settings.downloadDir
    startTimeDT = dateutil.parser.parse(args.startTime)
    if args.endTime:
        endTimeDT = dateutil.parser.parse(args.endTime)
    else:
        endTimeDT = startTimeDT
    assert startTimeDT.year == endTimeDT.year
    assert startTimeDT.month == endTimeDT.month
    assert startTimeDT.day == endTimeDT.day
    assert endTimeDT >= startTimeDT

    camArchives = img_archive.getHpwrenCameraArchives(googleServices['sheet'],
                                                      settings)
    files = img_archive.getHpwrenImages(googleServices, settings, outputDir,
                                        camArchives, args.cameraID,
                                        startTimeDT, endTimeDT, gapMinutes)
    if files:
        logging.warning('Found %d files.', len(files))
    else:
        logging.error('No matches for camera ID %s', args.cameraID)
Пример #3
0
def emailFireNotification(constants, cameraID, imgPath, annotatedFile,
                          driveFileIDs, fireSegment, timestamp):
    """Send an email alert for a potential new fire

    Send email with information about the camera and fire score includeing
    image attachments

    Args:
        constants (dict): "global" contants
        cameraID (str): camera name
        imgPath: filepath of the original image
        annotatedFile: filepath of the annotated image
        driveFileIDs (list): List of Google drive IDs for the uploaded image files
        fireSegment (dictionary): dictionary with information for the segment with fire/smoke
        timestamp (int): time.time() value when image was taken
    """
    dbManager = constants['dbManager']
    subject = 'Possible (%d%%) fire in camera %s' % (int(
        fireSegment['score'] * 100), cameraID)
    body = 'Please check the attached images for fire.'
    # commenting out links to google drive because they appear as extra attachments causing confusion
    # and some email recipients don't even have permissions to access drive.
    # for driveFileID in driveFileIDs:
    #     driveTempl = '\nAlso available from google drive as https://drive.google.com/file/d/%s'
    #     driveBody = driveTempl % driveFileID
    #     body += driveBody

    # emails are sent from settings.fuegoEmail and bcc to everyone with active emails in notifications SQL table
    dbResult = dbManager.getNotifications(filterActiveEmail=True)
    emails = [x['email'] for x in dbResult]
    if len(emails) > 0:
        # attach images spanning a few minutes so reviewers can evaluate based on progression
        startTimeDT = datetime.datetime.fromtimestamp(timestamp - 3 * 60)
        endTimeDT = datetime.datetime.fromtimestamp(timestamp - 1 * 60)
        with tempfile.TemporaryDirectory() as tmpDirName:
            oldImages = img_archive.getHpwrenImages(
                constants['googleServices'], settings, tmpDirName,
                constants['camArchives'], cameraID, startTimeDT, endTimeDT, 1)
            oldImages = oldImages or []
            attachments = oldImages + [imgPath, annotatedFile]
            email_helper.sendEmail(constants['googleServices']['mail'],
                                   settings.fuegoEmail, emails, subject, body,
                                   attachments)
Пример #4
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))