def main(): reqArgs = [ ['o', 'outputFile', 'filename for output CSV of fire x camera matches with available archives'], ] optionalArgs = [ ['g', 'longitude', 'longitude of fire', float], ['t', 'latitude', 'latitude of fire', float], ['s', 'startTime', 'start time of fire'], ] args = collect_args.collectArgs(reqArgs, optionalArgs=optionalArgs, parentParsers=[goog_helper.getParentParser()]) googleServices = goog_helper.getGoogleServices(settings, args) dbManager = db_manager.DbManager(sqliteFile=settings.db_file) outputFile = open(args.outputFile, 'w', newline='') outputCsv = csv.writer(outputFile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) camArchives = img_archive.getHpwrenCameraArchives(googleServices['sheet'], settings) locMatches = getLocationMatches(dbManager, args.longitude, args.latitude, args.startTime) totalMatches = len(locMatches) numOutput = 0 for rowNum,locMatch in enumerate(locMatches): timeDT = datetime.datetime.fromtimestamp(locMatch['timestamp']) cams = locMatch['cameraids'].split(',') availCams = [] for cameraID in cams: if isCamArchiveAvailable(camArchives, cameraID, timeDT): availCams.append(cameraID) # logging.warning('availCams %d: %s', len(availCams), availCams) if len(availCams) > 0: outputRow(outputCsv, locMatch, timeDT, availCams) numOutput += 1 if (rowNum % 10) == 0: logging.warning('Processing %d of %d, output %d', rowNum, totalMatches, numOutput) logging.warning('Processed %d, output %d', totalMatches, numOutput)
def main(): reqArgs = [] args = collect_args.collectArgs( reqArgs, optionalArgs=[], parentParsers=[goog_helper.getParentParser()]) dbManager = db_manager.DbManager(sqliteFile=settings.db_file) fires = getUnparsedFires(dbManager) parseDates(dbManager, fires)
def main(): reqArgs = [ ["f", "fileName", "name of file containing fire_coords.py output"], ] args = collect_args.collectArgs( reqArgs, optionalArgs=[], parentParsers=[goog_helper.getParentParser()]) dbManager = db_manager.DbManager(sqliteFile=settings.db_file) insertFires(dbManager, args.fileName)
def main(): reqArgs = [ ["m", "mode", "basemaps, city"], ] optArgs = [ ["l", "locationID", "camera locationID"], ] args = collect_args.collectArgs(reqArgs, optionalArgs=optArgs) dbManager = db_manager.DbManager(sqliteFile=settings.db_file, psqlHost=settings.psqlHost, psqlDb=settings.psqlDb, psqlUser=settings.psqlUser, psqlPasswd=settings.psqlPasswd) gmaps = googlemaps.Client(key=settings.mapsKey) locations = getCameraLocations(dbManager) if args.locationID: locations = list( filter(lambda x: x['locationid'] == args.locationID.strip(), locations)) for location in locations: logging.warning('loc %s', location) if args.mode == 'basemaps': mapFiles = [] for zoom in range(settings.MAP_ZOOM_MIN, settings.MAP_ZOOM_MAX + 1): mapFileGCS = uploadMapGCS(location['latitude'], location['longitude'], location['locationid'], zoom) mapFiles.append(mapFileGCS) if len(mapFiles) > 0: logging.warning('updating DB %s', location['locationid']) updateCameraMaps(dbManager, location['locationid'], mapFiles) elif args.mode == 'city': geoCodeRes = gmaps.reverse_geocode( (location['latitude'], location['longitude'])) for geoCodeComp in geoCodeRes: cityName = cityNameFromComp(geoCodeComp) if re.findall('^[A-Za-z ]+$', cityName): # contains only alphabet and spaces break logging.warning('city for %s is %s', location['locationid'], cityName) updateCameraCity(dbManager, location['locationid'], cityName)
def main(): reqArgs = [ ["m", "mapFile", "base map"], ["l", "leftLongitude", "longitude of left edge", float], ["r", "rightLongitude", "longitude of right edge", float], ["t", "topLatitude", "latitude of top edge", float], ["b", "bottomLatitude", "latitude of bottom edge", float], ] optArgs = [] args = collect_args.collectArgs(reqArgs, optionalArgs=optArgs) dbManager = db_manager.DbManager(sqliteFile=settings.db_file, psqlHost=settings.psqlHost, psqlDb=settings.psqlDb, psqlUser=settings.psqlUser, psqlPasswd=settings.psqlPasswd) locations = getCameraLocations(dbManager) logging.warning('Found %d locations', len(locations)) mapImg = Image.open(args.mapFile) assert args.leftLongitude < args.rightLongitude assert args.topLatitude > args.bottomLatitude diffLat = args.topLatitude - args.bottomLatitude diffLong = args.rightLongitude - args.leftLongitude radiusDegrees = 0.3 for location in locations: numNearby = len( list( filter( lambda x: ((x['longitude'] - location['longitude'])**2 + (x['latitude'] - location['latitude'])**2) < radiusDegrees**2, locations))) # logging.warning('loc %s, %s', location, numNearby) centerX = (location['longitude'] - args.leftLongitude) / diffLong * mapImg.size[0] centerY = mapImg.size[1] - (location['latitude'] - args.bottomLatitude ) / diffLat * mapImg.size[1] opacityRatio = min(4 / numNearby, 1) mapImg = drawCircle(mapImg, centerX, centerY, radiusDegrees / diffLat * mapImg.size[1], opacityRatio) mapImg.save('amap.jpg', quality=95)
def main(): reqArgs = [ ["m", "mode", "list, add, checkdb"], ] optArgs = [ ["s", "startTime", "starting date and time in ISO format (e.g., 2019-02-22T14:34:56 in Pacific time zone)"], ["c", "cameraID", "ID of the camera (e.g., mg-n-mobo-c)"], ["a", "heading", "view heading", int], ["w", "angularWidth", "ignored view width", int], ["n", "noState", "(optional) no changes to state"], ["f", "maxFalse", "(optional) maximum false positives to check (default 10)", int], ["r", "restrictType", "Only process images from cameras of given type"], ] args = collect_args.collectArgs(reqArgs, optionalArgs=optArgs) dbManager = db_manager.DbManager(sqliteFile=settings.db_file, psqlHost=settings.psqlHost, psqlDb=settings.psqlDb, psqlUser=settings.psqlUser, psqlPasswd=settings.psqlPasswd) ignoredViews = dbManager.get_ignoredViews() logging.warning('Num views: %d', len(ignoredViews)) numFalse = args.maxFalse if args.maxFalse else 10 if args.mode == 'list': logging.warning('All views: %s', ignoredViews) elif args.mode == 'add': addNew(dbManager, ignoredViews, args.cameraID, args.heading, args.angularWidth) elif args.mode == 'checkdb': recents = getRecentFalse(dbManager, numFalse, startTimeStr=args.startTime, restrictType=args.restrictType) for entry in recents: logging.warning('count %d: cam %s, camHead %s, min %s, max %s', entry['ct'], entry['cameraname'], entry['camheading'], entry['minx'], entry['maxx']) fov = img_archive.getCameraFov(entry['cameraname']) imgSizeX = img_archive.getCameraSizeX(entry['cameraname']) # logging.warning('cam %s: fov %s, sizeX %s', entry['cameraname'], fov, imgSizeX) (fireHeading, rangeAngle) = img_archive.getHeadingRange(entry['camheading'], fov, entry['minx'], entry['maxx'], imgSizeX) logging.warning('cam %s: fireHeading %s, rangeAngle %s', entry['cameraname'], round(fireHeading), round(rangeAngle)) if not args.noState: addNew(dbManager, ignoredViews, entry['cameraname'], fireHeading, rangeAngle) ignoredViews = dbManager.get_ignoredViews() # update state else: logging.error('unexpected mode: %s', args.mode) exit(1) return
Takes csv export of Images table and push it to sqlite DB """ import os, sys from firecam.lib import settings from firecam.lib import collect_args from firecam.lib import db_manager import time import csv import dateutil.parser manager = db_manager.DbManager(sqliteFile=settings.db_file, psqlHost=settings.psqlHost, psqlDb=settings.psqlDb, psqlUser=settings.psqlUser, psqlPasswd=settings.psqlPasswd) def insert_entire_images(csvFile): csvreader = csv.reader(csvFile) for row in csvreader: dt = dateutil.parser.parse(row[4]) unixTime = int(time.mktime(dt.timetuple())) parsed = { 'ImageID': row[0], 'ImageClass': row[1], 'FireName': row[2], 'CameraName': row[3], 'Timestamp': unixTime,
def main(): reqArgs = [ [ "s", "startTime", "starting date and time in ISO format (e.g., 2019-02-22T14:34:56 in Pacific time zone)" ], ] optArgs = [ ["c", "cameraID", "ID (code name) of camera"], ['n', 'longitude', 'longitude of fire', float], ['t', 'latitude', 'latitude of fire', float], [ 'm', 'maxDistance', '(optional default=20) max distance in miles from fire', float ], [ "e", "endTime", "ending date and time in ISO format (e.g., 2019-02-22T14:34:56 in Pacific time zone)" ], [ "d", "durationMinutes", "alternative spec for endTime as start + duration", int ], [ "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 distanceMiles = float(args.maxDistance if args.maxDistance else 20) outputDir = args.outputDir if args.outputDir else settings.downloadDir startTimeDT = dateutil.parser.parse(args.startTime) if args.endTime: endTimeDT = dateutil.parser.parse(args.endTime) elif args.durationMinutes: durationDelta = datetime.timedelta(seconds=60 * args.durationMinutes) endTimeDT = startTimeDT + durationDelta else: endTimeDT = startTimeDT assert startTimeDT.year == endTimeDT.year assert startTimeDT.month == endTimeDT.month assert startTimeDT.day == endTimeDT.day assert endTimeDT >= startTimeDT if args.cameraID: assert (not args.latitude) and (not args.longitude) cameras = [args.cameraID] else: assert args.latitude and args.longitude dbManager = db_manager.DbManager(sqliteFile=settings.db_file, psqlHost=settings.psqlHost, psqlDb=settings.psqlDb, psqlUser=settings.psqlUser, psqlPasswd=settings.psqlPasswd) cameras = getNearbyCameras(dbManager, args.latitude, args.longitude, distanceMiles) logging.warning('Matched cmaeras: %s', cameras) camArchives = img_archive.getHpwrenCameraArchives(settings.hpwrenArchives) allFiles = [] for cameraID in cameras: camFiles = img_archive.getHpwrenImages(googleServices, settings, outputDir, camArchives, cameraID, startTimeDT, endTimeDT, gapMinutes) if camFiles: allFiles += camFiles if allFiles: logging.warning('Found %d files.', len(allFiles)) else: logging.error('No filed matched')
def main(): reqArgs = [ ["o", "outputFile", "output file name"], ["i", "inputCsv", "csvfile with fire/detection data"], ['m', "mode", "mode: votepoly or camdir or pruned"], ] optArgs = [ ["s", "startRow", "starting row"], ["e", "endRow", "ending row"], ] 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 mode = args.mode assert mode == 'votepoly' or mode == 'camdir' or mode == 'pruned' outFile = open(args.outputFile, 'w') dbManager = db_manager.DbManager(sqliteFile=settings.db_file, psqlHost=settings.psqlHost, psqlDb=settings.psqlDb, psqlUser=settings.psqlUser, psqlPasswd=settings.psqlPasswd) lastCam = None lastTime = None random.seed(0) 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 if mode == 'votepoly': [cameraID, timestamp, score, polygon, sourcePolygons, isRealFire] = csvRow[:6] timestamp = int(timestamp) logging.warning('Processing row: %d, cam: %s, ts: %s', rowIndex, cameraID, timestamp) if cameraID == lastCam and timestamp == lastTime: logging.warning('Duplicate row: %d, cam: %s, ts: %s', rowIndex, cameraID, timestamp) lastCam = cameraID lastTime = timestamp centroid = getCentroid(polygon) if timestamp < 1607786165: #sourcePolygons didn't exist before this if isRealFire: numPolys = round(getRandInterpolatedVal(settings.percentilesNumPolyFire)) else: numPolys = round(getRandInterpolatedVal(settings.percentilesNumPolyOther)) else: numPolys = 1 if sourcePolygons: sourcePolygonsArr = json.loads(sourcePolygons) numPolys = len(sourcePolygonsArr) cameraID = patchCameraId(cameraID) camInfo = dbManager.getCameraMapLocation(cameraID) if camInfo == None: logging.warning('Skipping row with camera without meta %s', cameraID) continue (mapImgGCS, camLatitude, camLongitude) = camInfo else: if mode == 'camdir': [cameraID, isoTime, direction] = csvRow[:3] logging.warning('Processing row: %d, cam: %s, ts: %s', rowIndex, cameraID, isoTime) timestamp = time.mktime(dateutil.parser.parse(isoTime).timetuple()) if 'center left' in direction: offset = -20 elif 'center right' in direction: offset = 20 elif 'center' in direction: offset = 0 elif 'left' in direction: offset = -40 elif 'right' in direction: offset = 40 else: logging.error('Unexpected dir row: %d, dir: %s', rowIndex, direction) continue elif mode == 'pruned': [_cropName, minX, _minY, maxX, _maxY, fileName] = csvRow[:6] minX = int(minX) maxX = int(maxX) nameParsed = img_archive.parseFilename(fileName) cameraID = nameParsed['cameraID'] cameraID = patchCameraId(cameraID) timestamp = nameParsed['unixTime'] dateStr = nameParsed['isoStr'][:nameParsed['isoStr'].index('T')] if dateStr == lastTime and cameraID == lastCam: # logging.warning('Skip same fire. row %s', rowIndex) continue lastCam = cameraID lastTime = dateStr localFilePath = os.path.join(settings.downloadDir, fileName) if not os.path.isfile(localFilePath): logging.warning('Skip missing file %s, row %s', fileName, rowIndex) continue img = Image.open(localFilePath) degreesInView = img_archive.getCameraFov(cameraID) centerX = (minX + maxX) / 2 offset = centerX / img.size[0] * degreesInView - degreesInView/2 img.close() (mapImgGCS, camLatitude, camLongitude) = dbManager.getCameraMapLocation(cameraID) camHeading = img_archive.getHeading(cameraID) heading = (camHeading + offset) % 360 angle = 90 - heading distanceDegrees = 0.2 # approx 14 miles fireLat = camLatitude + math.sin(angle*math.pi/180)*distanceDegrees fireLong = camLongitude + math.cos(angle*math.pi/180)*distanceDegrees centroid = (fireLat, fireLong) score = getRandInterpolatedVal(settings.percentilesScoreFire) numPolys = round(getRandInterpolatedVal(settings.percentilesNumPolyFire)) isRealFire = 1 logging.warning('Processing row: %d, heading: %s, centroid: %s, score: %s, numpoly: %s', rowIndex, heading, centroid, score, numPolys) if not keepData(score, centroid, numPolys, isRealFire): logging.warning('Skipping Mexico fire row %d, camera %s', rowIndex, cameraID) continue (weatherCentroid, weatherCamera) = weather.getWeatherData(dbManager, cameraID, timestamp, centroid, (camLatitude, camLongitude)) if not weatherCentroid: logging.warning('Skipping row %d', rowIndex) continue # logging.warning('Weather %s', weatherCentroid) outputWithWeather(outFile, score, timestamp, centroid, numPolys, weatherCentroid, weatherCamera, isRealFire) logging.warning('Processed row: %d, cam: %s, ts: %s', rowIndex, cameraID, timestamp) outFile.close()
def main(): reqArgs = [ ["o", "operation", "add (includes update), delete, list"], ] optArgs = [ ["n", "name", "name (ID) of user"], ["m", "email", "email address of user"], ["p", "phone", "phone number of user"], ["s", "startTime", "starting date and time in ISO format (e.g., 2019-02-22T14:34:56 in Pacific time zone)"], ["e", "endTime", "ending date and time in ISO format (e.g., 2019-02-22T14:34:56 in Pacific time zone)"], ] args = collect_args.collectArgs(reqArgs, optionalArgs=optArgs) startTime = parseTimeStr(args.startTime) if args.startTime else None endTime = parseTimeStr(args.endTime) if args.endTime else None dbManager = db_manager.DbManager(sqliteFile=settings.db_file, psqlHost=settings.psqlHost, psqlDb=settings.psqlDb, psqlUser=settings.psqlUser, psqlPasswd=settings.psqlPasswd) notifications = dbManager.getNotifications() activeEmails = dbManager.getNotifications(filterActiveEmail=True) activePhones = dbManager.getNotifications(filterActivePhone=True) logging.warning('Num all notifications: %d. Active emails: %d. Active phones: %d', len(notifications), len(activeEmails), len(activePhones)) if args.operation == 'list': for n in notifications: printNoficiation(n) return assert args.name matching = list(filter(lambda x: x['name'] == args.name, notifications)) logging.warning('Found %d matching for name %s', len(matching), args.name) if matching: printNoficiation(matching[0]) if args.operation == 'add': assert startTime and endTime assert endTime >= startTime assert args.email or args.phone if not matching: # insert new entry dbRow = { 'name': args.name, } if args.email: dbRow['email'] = args.email dbRow['EmailStartTime'] = startTime dbRow['EmailEndTime'] = endTime if args.phone: dbRow['phone'] = args.phone dbRow['PhoneStartTime'] = startTime dbRow['PhoneEndTime'] = endTime dbManager.add_data('notifications', dbRow) logging.warning('Successfully added notification for %s', args.name) else: # update existing entry if args.email: sqlTemplate = """UPDATE notifications SET email='%s',EmailStartTime=%s,EmailEndTime=%s WHERE name = '%s' """ sqlStr = sqlTemplate % (args.email, startTime, endTime, args.name) dbManager.execute(sqlStr) if args.phone: sqlTemplate = """UPDATE notifications SET phone='%s',PhoneStartTime=%s,PhoneEndTime=%s WHERE name = '%s' """ sqlStr = sqlTemplate % (args.phone, startTime, endTime, args.name) dbManager.execute(sqlStr) logging.warning('Successfully updated notification for %s', args.name) notifications = dbManager.getNotifications() matching = list(filter(lambda x: x['name'] == args.name, notifications)) printNoficiation(matching[0]) elif args.operation == 'delete': sqlTemplate = """DELETE FROM notifications WHERE name = '%s' """ sqlStr = sqlTemplate % (args.name) dbManager.execute(sqlStr) else: logging.error('Unexpected operation: %s', args.operation)
def main(): reqArgs = [ ["m", "mode", "add, delete, enable, disable, stats, or list"], ] optArgs = [ ["c", "cameraID", "ID of the camera (e.g., mg-n-mobo-c)"], ["u", "url", "url to get images from camera"], ] args = collect_args.collectArgs(reqArgs, optionalArgs=optArgs) dbManager = db_manager.DbManager(sqliteFile=settings.db_file, psqlHost=settings.psqlHost, psqlDb=settings.psqlDb, psqlUser=settings.psqlUser, psqlPasswd=settings.psqlPasswd) cameraInfos = dbManager.get_sources(activeOnly=False) logging.warning('Num all cameras: %d', len(cameraInfos)) logging.warning('Num active cameras: %d', len(list(filter(lambda x: x['dormant'] == 0, cameraInfos)))) if args.mode == 'list': logging.warning('All cameras: %s', list(map(lambda x: x['name'], cameraInfos))) return matchingCams = list(filter(lambda x: x['name'] == args.cameraID, cameraInfos)) logging.warning('Found %d matching cams for ID %s', len(matchingCams), args.cameraID) if args.mode == 'add': if len(matchingCams) != 0: logging.error('Camera with ID %s already exists: %s', args.cameraID, matchingCams) exit(1) dbRow = { 'name': args.cameraID, 'url': args.url, 'dormant': 0, 'randomID': random.random(), 'last_date': datetime.datetime.now().isoformat() } dbManager.add_data('sources', dbRow) logging.warning('Successfully added camera %s', args.cameraID) return if len(matchingCams) != 1: logging.error('Cannot find camera with ID %s: %s', args.cameraID, matchingCams) exit(1) camInfo = matchingCams[0] logging.warning('Cam details: %s', camInfo) if args.mode == 'delete': sqlTemplate = """DELETE FROM sources WHERE name = '%s' """ execCameraSql(dbManager, sqlTemplate, args.cameraID, isQuery=False) return if args.mode == 'enable': if camInfo['dormant'] == 0: logging.error('Camera already enabled: dormant=%d', camInfo['dormant']) exit(1) sqlTemplate = """UPDATE sources SET dormant=0 WHERE name = '%s' """ execCameraSql(dbManager, sqlTemplate, args.cameraID, isQuery=False) return if args.mode == 'disable': if camInfo['dormant'] == 1: logging.error('Camera already disabled: dormant=%d', camInfo['dormant']) exit(1) sqlTemplate = """UPDATE sources SET dormant=1 WHERE name = '%s' """ execCameraSql(dbManager, sqlTemplate, args.cameraID, isQuery=False) return if args.mode == 'stats': sqlTemplate = """SELECT max(timestamp) as maxtime FROM scores WHERE CameraName = '%s' """ dbResult = execCameraSql(dbManager, sqlTemplate, args.cameraID, isQuery=True) logging.warning('Most recent image scanned: %s', getTime(dbResult)) sqlTemplate = """SELECT max(timestamp) as maxtime FROM detections WHERE CameraName = '%s' """ dbResult = execCameraSql(dbManager, sqlTemplate, args.cameraID, isQuery=True) logging.warning('Most recent smoke detection: %s', getTime(dbResult)) sqlTemplate = """SELECT max(timestamp) as maxtime FROM alerts WHERE CameraName = '%s' """ dbResult = execCameraSql(dbManager, sqlTemplate, args.cameraID, isQuery=True) logging.warning('Most recent smoke alert: %s', getTime(dbResult)) return logging.error('Unexpected mode: %s', args.mode) exit(1)
def main(): optArgs = [ ["b", "heartbeat", "filename used for heartbeating check"], ["c", "collectPositves", "collect positive segments for training data"], ["t", "time", "Time breakdown for processing images"], ["m", "minusMinutes", "(optional) subtract images from given number of minutes ago"], ["r", "restrictType", "Only process images from cameras of given type"], ["s", "startTime", "(optional) performs search with modifiedTime > startTime"], ["e", "endTime", "(optional) performs search with modifiedTime < endTime"], ] args = collect_args.collectArgs([], optionalArgs=optArgs, parentParsers=[goog_helper.getParentParser()]) minusMinutes = int(args.minusMinutes) if args.minusMinutes else 0 # TODO: Fix googleServices auth to resurrect email alerts # googleServices = goog_helper.getGoogleServices(settings, args) googleServices = None dbManager = db_manager.DbManager(sqliteFile=settings.db_file, psqlHost=settings.psqlHost, psqlDb=settings.psqlDb, psqlUser=settings.psqlUser, psqlPasswd=settings.psqlPasswd) cameras = dbManager.get_sources(activeOnly=True, restrictType=args.restrictType) startTimeDT = dateutil.parser.parse(args.startTime) if args.startTime else None endTimeDT = dateutil.parser.parse(args.endTime) if args.endTime else None timeRangeSeconds = None useArchivedImages = False camArchives = img_archive.getHpwrenCameraArchives(settings.hpwrenArchives) DetectionPolicyClass = policies.get_policies()[settings.detectionPolicy] detectionPolicy = DetectionPolicyClass(args, dbManager, minusMinutes, stateless=useArchivedImages) constants = { # dictionary of constants to reduce parameters in various functions 'args': args, 'googleServices': googleServices, 'camArchives': camArchives, 'dbManager': dbManager, } if startTimeDT or endTimeDT: assert startTimeDT and endTimeDT timeRangeSeconds = (endTimeDT-startTimeDT).total_seconds() assert timeRangeSeconds > 0 assert args.collectPositves useArchivedImages = True random.seed(0) # fixed seed guarantees same randomized ordering. Should make this optional argument in future processingTimeTracker = initializeTimeTracker() while True: classifyImgPath = None timeStart = time.time() if useArchivedImages: (cameraID, timestamp, imgPath, classifyImgPath) = \ getArchivedImages(constants, cameras, startTimeDT, timeRangeSeconds, minusMinutes) # elif minusMinutes: to be resurrected using archive functionality else: # regular (non diff mode), grab image and process (cameraID, timestamp, imgPath, md5) = getNextImage(dbManager, cameras) classifyImgPath = imgPath if not cameraID: continue # skip to next camera timeFetch = time.time() image_spec = [{}] image_spec[-1]['path'] = classifyImgPath image_spec[-1]['timestamp'] = timestamp image_spec[-1]['cameraID'] = cameraID detectionResult = detectionPolicy.detect(image_spec) timeDetect = time.time() if detectionResult['fireSegment']: if not isDuplicateAlert(dbManager, cameraID, timestamp): alertFire(constants, cameraID, timestamp, imgPath, detectionResult['fireSegment']) deleteImageFiles(imgPath, imgPath) if (args.heartbeat): heartBeat(args.heartbeat) timePost = time.time() updateTimeTracker(processingTimeTracker, timePost - timeStart) if args.time: if not detectionResult['timeMid']: detectionResult['timeMid'] = timeDetect logging.warning('Timings: fetch=%.2f, detect0=%.2f, detect1=%.2f post=%.2f', timeFetch-timeStart, detectionResult['timeMid']-timeFetch, timeDetect-detectionResult['timeMid'], timePost-timeDetect) # free all memory for current iteration and trigger GC to prevent memory growth detectionResult = None gc.collect()