Beispiel #1
0
  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]
Beispiel #2
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()
Beispiel #3
0
    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)
Beispiel #4
0
    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)