parser.add_option('--seed', help='Seed for the random number generator', default=986725, type='int') parser.add_option('--frame_regex', default='(([0-9][0-9]-){3}[0-9]+)\.', help='Regex to extract the frame id from filenames') parser.add_option('-i', '--input', default=None, help='File with blobs listed one per line') parser.add_option('--min_size', type='int', default=100, help='Minimum blob size to accept in pixels') (options, args) = parser.parse_args() frameRe = re.compile(options.frame_regex) blobSerializer = Blob.BlobSerializer() prefix = options.prefix if prefix is None: prefix = '' negBlobDir = os.path.dirname(prefix) if not os.path.exists(negBlobDir): os.makedirs(negBlobDir) for line in open(options.input): filename = line.strip() foundFrame = frameRe.search(filename) if foundFrame: frameId = foundFrame.groups()[0]
def RunOneExtraction(fishEntries, negEntries, blobDir, experimentDir, outputPrefix, videoId=None, shapeDictFilename=None, useSurfDescriptor=False, useSiftDescriptor=False, useOpponentSurf=False, useCInvariantSurf=False, saveIndex=False, hessThresh=400.0, numNegBlobs=5.0, options=None): # Split up the training and test entries if videoId is not None: trainEntries = filter(lambda x: x[2] <> videoId, fishEntries) trainNegEntries = filter(lambda x: x[1] <> videoId, negEntries) testEntries = filter(lambda x: x[2] == videoId, fishEntries) testBlobFiles = sorted(set([x[0] for x in testEntries])) rospy.loginfo('Testing with entries of video id ' + videoId) else: rospy.logfatal('Must have a video id. We are done') return runName = GetRandomRunName() # Now build up a list of training and negative entries entries to be # used by the BuildFishIndex program. labelFilename = os.path.join(experimentDir, 'train_%s.label' % runName) labelFile = open(labelFilename, 'w') try: for blobFile, blobId, trainVideoId, label in trainEntries: labelFile.write('%s,%i,%s\n' % (blobFile, blobId, label)) WriteNegativeExamples(labelFile, trainNegEntries, numNegBlobs * len(trainEntries), blobDir) finally: labelFile.close() # Setup the parameters used by the routines paramList = [('color_dict_filename', ''), ('color_converter', ''), ('color_frac', 0), ('shape_dict_filename', shapeDictFilename), ('surf_detector', True), ('surf_hessian_threshold', hessThresh), ('surf_octaves', 3), ('surf_octave_layers', 4), ('surf_extended', False), ('surf_descriptor', useSurfDescriptor), ('sift_descriptor', useSiftDescriptor), ('shape_weight', 1.0), ('min_shape_val', 0.01), ('min_color_val', 0.01), ('min_score', 0.005), ('opponent_color_surf', useOpponentSurf), ('cinvariant_color_surf', useCInvariantSurf), ('use_bounding_box', True), ('bounding_box_expansion', 1.0), ('geometric_rerank', False), ('geo_rerank_inlier_thresh', 3.0)] rospy.loginfo('Using parameters: ' + str(paramList)) indexFilename = os.path.join(experimentDir, 'train_%s.index' % runName) # Build the search index for the fish BuildFishIndex(labelFilename, indexFilename, blobDir, paramList) # Open up the bag which we will output stuff to resultFile = '%s_%s.bag' % (outputPrefix, videoId) outBag = rosbag.Bag(os.path.join(experimentDir, resultFile), 'w', 'bz2') # Start a SpeciesIDNode to serve the requests and grab the service # hook to it speciesIdProc, speciesIdParams, ClassifyGrid = StartSpeciesIDNode( experimentDir, runName, outBag, rospy.Time.from_sec(0.0), paramList, indexFilename) try: blobSerializer = Blob.BlobSerializer() cvBridge = cv_bridge.CvBridge() npBridge = cv_bridge.NumpyBridge() curFrameNum = 0 for blobFile in testBlobFiles: # The result message to store resultMsg = SpeciesIDScoring() # Read the blob file blobStream = open(os.path.join(blobDir, blobFile), 'r') try: blobs, imageFile = blobSerializer.Deserialize( blobStream, blobDir) finally: blobStream.close() rospy.loginfo('Processing %s' % imageFile) # Fill out the ground truth in the result message curEntries = filter(lambda x: x[0] == blobFile, testEntries) curEntries = sorted(curEntries, key=lambda x: x[1]) curBlobId = 0 for blob in blobs: curEntry = [x for x in curEntries if x[1] == curBlobId] if len(curEntry) == 1 and int(curEntry[0][3]) > 3: # The human label says it's a fish so add the label to the results resultMsg.labels.append(int(curEntries[curBlobId][3])) bbox = RegionOfInterest() bbox.x_offset = blob.minX bbox.y_offset = blob.minY bbox.height = blob.maxY - blob.minY bbox.width = blob.maxX - blob.minX resultMsg.regions.append(bbox) curBlobId += 1 # Open up the image and package it into a message cvImage = cv2.imread(imageFile) imgMsg = cvBridge.cv_to_imgmsg(cvImage, 'bgr8') imgMsg.header.stamp = rospy.Time.from_sec(curFrameNum) imgMsg.header.seq = curFrameNum # Build up the request request = DetectObjectGrid() request.header = imgMsg.header request.image = imgMsg request.grid.minX = 0 request.grid.minY = 0 request.grid.minH = options.min_region_height request.grid.minW = options.min_region_width request.grid.strideX = options.win_stride request.grid.strideY = options.win_stride request.grid.strideH = options.scale_stride request.grid.strideW = options.scale_stride request.grid.fixAspect = False request.mask.encoding = "8U" # Process this image response = ClassifyGrid(request) # Build up the result message to store resultMsg.image = imageFile resultMsg.grid = response.grid resultMsg.confidence = response.confidence resultMsg.top_label = response.top_label resultMsg.not_fish_confidence = response.not_fish_confidence resultMsg.processing_time = response.processing_time # Record the result in the bag file outBag.write('results', resultMsg, request.header.stamp) outBag.flush() curFrameNum += 1 finally: outBag.close() speciesIdParams.RemoveParameters() ClassifyGrid.close() speciesIdProc.send_signal(2) tries = 0 while speciesIdProc.returncode == None and tries < 10: speciesIdProc.poll() tries = tries + 1 time.sleep(1) if speciesIdProc.returncode == None: speciesIdProc.kill() if not options.save_index: os.remove(indexFilename) gc.collect()
def __init__(self, inputBags, md5=None, frameSubsetRate=1, blobDir=None, overlapThresh=0.5, allowInvalidScores=False): self.InitData() self.md5 = md5 blobReader = Blob.BlobSerializer() ndBridge = cv_bridge.NumpyBridge() curFileId = 0 for bagFn in inputBags: rospy.loginfo('Reading bag ' + bagFn) curParams = {} curBag = rosbag.Bag(bagFn) self.bagIdx.append((len(self.scores), len(self.maxOverlapScore))) try: for topic, msg, t in curBag.read_messages(topics=['results']): if topic == 'parameters': # Store the parameter as strings curParams[msg.name.data] = msg.value.data if topic == 'results': if curFileId % frameSubsetRate <> 0: curFileId += 1 continue rospy.loginfo('Processing ' + msg.image) blobFn = img2blobFn(msg.image, blobDir) self.fileIdMap[curFileId] = blobFn self.fileMap[blobFn] = curFileId self.processingTime.append( msg.scores.processing_time.data.to_sec()) image = cv2.imread(msg.image, 0) scoreStartIdx = len(self.scores) blobStream = open(blobFn) try: blobs, garb = blobReader.Deserialize( blobStream, blobDir) regions = DetectionUtils.GenerateSamplingRegions( image.shape, msg.scores.grid) scoreGrid = ndBridge.matmsg_to_numpy( msg.scores.scores) validScores = np.nonzero(np.isfinite(scoreGrid)) curOverlaps = overlaps if not allowInvalidScores: curOverlaps = overlaps[validScores] bestOverlaps = np.zeros((len(curOverlaps))) curBlobId = 0 for blob in blobs: curLoc = (blob.minX, blob.minY, blob.maxY - blob.minY, blob.maxX - blob.minX) self.blobList.append((curFileId, curBlobId)) self.fishLoc.append(curLoc) overlaps = DetectionUtils.CalculateOverlapWithGrid( curLoc, regions) # Get the maximum score that overlaps the fish validOverlaps = np.nonzero( overlaps > overlapThresh) if len(validOverlaps[0]) > 0: self.maxOverlapScore.append( np.amax(scoreGrid[validOverlaps])) else: self.maxOverlapScore.append(float('-inf')) # Keep track of the maximum overlap for each location bestOverlaps = np.maximum( bestOverlaps, curOverlaps) curBlobId += 1 # Store the scores and best overlaps for this file if allowInvalidScores: self.scores = np.hstack( (self.scores, scoreGrid)) else: self.scores = np.hstack( (self.scores, scoreGrid[validScores])) self.overlaps = np.hstack( (self.overlaps, bestOverlaps)) # Keep track of the range where the scores are for this file self.fileRange[curFileId] = (scoreStartIdx, len(self.scores)) finally: blobStream.close() curFileId += 1 finally: curBag.close() self.params[bagFn] = curParams self.maxOverlapScore = np.array(self.maxOverlapScore)
parser.add_option('--output', '-o', dest='output', help='Optional output image file', default=None) parser.add_option( '--skip_display', action='store_false', dest='show_display', default=True, help='The image will not be shown if this flag is included.') (options, args) = parser.parse_args() # Open the blob file blobSerializer = Blob.BlobSerializer() f = open(options.input) try: (blobs, imgName) = blobSerializer.Deserialize(f, os.path.dirname(options.input)) finally: f.close() # Open the image image = cv2.imread(imgName) # Draw the red boxes around the blobs for blob in blobs: box = blob.GetBoundingBox() cv2.rectangle(image, box[0:2], box[2:4], (0, 0, 255, 0.5), 1)