Beispiel #1
0
        /// <summary>
        /// assign stereo features to the given camera
        /// </summary>
        /// <param name="camera_index">stereo camera index</param>
        /// <param name="featurelist">stereo features</param>
        /// <param name="uncertainties">governs the standard deviation used when ray throwing</param>
        /// <param name="no_of_features">number of stereo features</param>
        public void setStereoFeatures(int camera_index,
                                      float[] featurelist,
                                      float[] uncertainties,
                                      int no_of_features)
        {
            if (features[camera_index] == null)
            {
                features[camera_index] = new stereoFeatures(no_of_features);
            }

            if (featurelist != null)
            {
                features[camera_index].no_of_features = no_of_features;
                features[camera_index].features       = (float[])featurelist.Clone();
                if (uncertainties != null)
                {
                    features[camera_index].uncertainties = (float[])uncertainties.Clone();
                }
            }
            else
            {
                features[camera_index].no_of_features = 0;
                features[camera_index].features       = null;
            }
        }
Beispiel #2
0
 /// <summary>
 /// match this feature set with another
 /// </summary>
 /// <param name="other">the other feature set</param>
 /// <param name="match_indexes">array which contains the matching indexes</param>
 /// <param name="img_width">image width</param>
 /// <param name="img_height">image height</param>
 /// <param name="max_displacement">maximum horizontal displacement as a percentage 1-100</param>
 public void match(stereoFeatures other, int[] match_indexes,
                   int img_width, int img_height,
                   int max_displacement_x, int max_displacement_y,
                   bool overwrite)
 {
     matchTemporal(other.no_of_features, other.features,
                   no_of_features, features,
                   match_indexes, img_width, img_height,
                   max_displacement_x, max_displacement_y,
                   overwrite);
 }
Beispiel #3
0
        /// <summary>
        /// load stereo features for all cameras
        /// </summary>
        /// <param name="binfile">file to load from</param>
        public void loadStereoFeatures(BinaryReader binfile)
        {
            for (int i = 0; i < no_of_stereo_cameras; i++)
            {
                // create a new object
                stereoFeatures feat = new stereoFeatures(1);

                // load features for this camera
                feat.load(binfile);

                // update the head with these features
                setStereoFeatures(i, feat);
            }
        }
Beispiel #4
0
        /// <summary>
        /// load a pair of images
        /// </summary>
        private float loadImages(int stereo_cam_index, Byte[] fullres_left, Byte[] fullres_right, stereoHead head, int no_of_stereo_features, int bytes_per_pixel,
                                 int algorithm_type)
        {
            stereointerface.loadImage(fullres_left, head.calibration[stereo_cam_index].leftcam.image_width, head.calibration[stereo_cam_index].leftcam.image_height, true, bytes_per_pixel);

            stereointerface.loadImage(fullres_right, head.calibration[stereo_cam_index].leftcam.image_width, head.calibration[stereo_cam_index].leftcam.image_height, false, bytes_per_pixel);

            // calculate stereo disparity features
            int peaks_per_row = 5;

            stereointerface.stereoMatchRun(0, peaks_per_row, algorithm_type);

            // retrieve the features
            stereoFeatures feat = new stereoFeatures(no_of_stereo_features);
            int            no_of_selected_features = 0;
            stereoFeatures features;

            no_of_selected_features = stereointerface.getSelectedPointFeatures(feat.features);
            if (no_of_selected_features > 0)
            {
                if (no_of_selected_features == no_of_stereo_features)
                {
                    features = feat;
                }
                else
                {
                    features = new stereoFeatures(no_of_selected_features);
                    for (int f = 0; f < no_of_selected_features * 3; f++)
                    {
                        features.features[f] = feat.features[f];
                    }
                }

                // update the head with these features
                head.setStereoFeatures(stereo_cam_index, features);

                // update the colours for each feature
                head.updateFeatureColours(stereo_cam_index, fullres_left);
            }

            if (no_of_selected_features > 0) //no_of_stereo_features * 4 / 10)
            {
                return(stereointerface.getAverageMatchingScore());
            }
            else
            {
                return(-1);
            }
        }
Beispiel #5
0
        /// <summary>
        /// update the radar
        /// </summary>
        /// <param name="img_width"></param>
        /// <param name="img_height"></param>
        /// <param name="features"></param>
        public void update(int img_width, int img_height,
                           stereoFeatures features)
        {
            if (ranges_horizontal == null)
            {
                ranges_horizontal     = new float[img_width];
                ranges_vertical       = new float[img_height];
                rawranges_horizontal  = new float[img_width];
                tempranges_horizontal = new float[img_width];
                rawranges_vertical    = new float[img_height];
                variation_horizontal  = new float[img_width];
                variation_vertical    = new float[img_height];
                //av_variation_horizontal = new float[img_width];
                hits_horizontal = new int[img_width];
                hits_vertical   = new int[img_height];
                img             = new Byte[img_width * img_height * 3];
                for (int h = 0; h < img_height; h++)
                {
                    rawranges_vertical[h] = 0;
                    hits_vertical[h]      = 0;
                }
                for (int w = 0; w < img_width; w++)
                {
                    rawranges_horizontal[w] = 0;
                    hits_horizontal[w]      = 0;
                    //av_variation_horizontal[w] = 0;
                }
            }
            for (int h = 0; h < img_height; h++)
            {
                variation_vertical[h] = ranges_vertical[h];
                rawranges_vertical[h] = 0;
                hits_vertical[h]      = 0;
            }
            for (int w = 0; w < img_width; w++)
            {
                variation_horizontal[w] = ranges_horizontal[w];
                rawranges_horizontal[w] = 0;
                hits_horizontal[w]      = 0;
            }

            for (int i = 0; i < features.no_of_features; i++)
            {
                int   x    = (int)features.features[i * 3];
                int   y    = (int)features.features[(i * 3) + 1];
                float disp = features.features[(i * 3) + 2];
                if (disp > 0)
                {
                    float dist = 1 / disp;
                    rawranges_horizontal[x] += dist;
                    hits_horizontal[x]++;
                    rawranges_vertical[y] += dist;
                    hits_vertical[y]++;
                }
            }

            // clear the image
            for (int i = 0; i < img_width * img_height * 3; i++)
            {
                img[i] = 0;
            }

            for (int w = 0; w < img_width; w++)
            {
                if (hits_horizontal[w] > 0)
                {
                    rawranges_horizontal[w]  = rawranges_horizontal[w] * scale / hits_horizontal[w];
                    variation_horizontal[w] -= rawranges_horizontal[w];
                    ranges_horizontal[w]     = rawranges_horizontal[w];
                    tempranges_horizontal[w] = ranges_horizontal[w];
                }
            }

            // smooth out noise
            int prev_range_index  = -1;
            int prev_range_index2 = -1;

            for (int smooth = 0; smooth < smoothing_steps; smooth++)
            {
                for (int w = 1; w < img_width - 1; w++)
                {
                    if (hits_horizontal[w] > 0)
                    {
                        if ((prev_range_index > -1) && (prev_range_index2 > -1))
                        {
                            ranges_horizontal[prev_range_index] = (tempranges_horizontal[w] + tempranges_horizontal[prev_range_index] + tempranges_horizontal[prev_range_index2]) / 3.0f;
                        }
                        prev_range_index2 = prev_range_index;
                        prev_range_index  = w;
                    }
                }
                for (int w = 1; w < img_width - 1; w++)
                {
                    if (hits_horizontal[w] > 0)
                    {
                        tempranges_horizontal[w] = ranges_horizontal[w];
                    }
                }
            }


            prev_range_index  = -1;
            prev_range_index2 = -1;
            for (int w = 0; w < img_width; w++)
            {
                if (hits_horizontal[w] > 0)
                {
                    if (variation_horizontal[w] < 0)
                    {
                        variation_horizontal[w] = -variation_horizontal[w];
                    }

                    if (ranges_horizontal[w] > 0.01f)
                    {
                        hits_horizontal[w] = 1;
                    }
                    else
                    {
                        hits_horizontal[w] = 0;
                    }
                    prev_range_index2 = prev_range_index;
                    prev_range_index  = w;
                }
            }

            prev_range_index  = -1;
            prev_range_index2 = -1;
            for (int h = 0; h < img_height; h++)
            {
                if (hits_vertical[h] > 0)
                {
                    rawranges_vertical[h]  = rawranges_vertical[h] * scale / hits_vertical[h];
                    variation_vertical[h] -= rawranges_vertical[h];
                    ranges_vertical[h]     = rawranges_vertical[h];
                    if ((h > 0) && (h < img_height - 1) &&
                        (prev_range_index > -1) && (prev_range_index2 > -1))
                    {
                        ranges_vertical[prev_range_index] = (rawranges_vertical[h] + rawranges_vertical[prev_range_index] + rawranges_vertical[prev_range_index2]) / 3.0f;
                    }

                    if (variation_vertical[h] < 0)
                    {
                        variation_vertical[h] = -variation_vertical[h];
                    }

                    if (ranges_vertical[h] > 0.01f)
                    {
                        hits_vertical[h] = 1;
                    }
                    else
                    {
                        hits_vertical[h] = 0;
                    }
                    prev_range_index2 = prev_range_index;
                    prev_range_index  = h;
                }
            }



            int prev_x = 0;
            int prev_y = 0;

            //overhead
            for (int w = 0; w < img_width; w++)
            {
                if ((hits_horizontal[w] > 0) && (ranges_horizontal[w] > 0.01f))
                {
                    if ((variation_horizontal[w] < 50) && (variation_horizontal[prev_x] < 50))
                    {
                        if (prev_x > 0)
                        {
                            for (int xx = prev_x + 1; xx < w; xx++)
                            {
                                ranges_horizontal[xx] = ranges_horizontal[prev_x] + ((xx - prev_x) * (ranges_horizontal[w] - ranges_horizontal[prev_x]) / (w - prev_x));
                                hits_horizontal[xx]   = 1;
                            }
                            if (display_type == 0)
                            {
                                if (((int)ranges_horizontal[w] > 0) && ((int)ranges_horizontal[w] < img_height))
                                {
                                    drawing.drawLine(img, img_width, img_height, w, img_height - 1 - (int)ranges_horizontal[w], prev_x, prev_y, 0, 255, 0, 1, false);
                                }
                            }
                        }
                        prev_x = w;
                        prev_y = img_height - 1 - (int)ranges_horizontal[w];
                    }
                }
            }

            //side
            prev_x = 0;
            prev_y = 0;
            for (int h = 0; h < img_height; h++)
            {
                if ((hits_vertical[h] > 0) && (ranges_vertical[h] > 0.01f))
                {
                    if ((variation_vertical[h] < 50) && (variation_vertical[prev_y] < 50))
                    {
                        if (prev_y > 0)
                        {
                            for (int yy = prev_y + 1; yy < h; yy++)
                            {
                                ranges_vertical[yy] = ranges_vertical[prev_y] + ((yy - prev_y) * (ranges_vertical[h] - ranges_vertical[prev_y]) / (h - prev_y));
                                hits_vertical[yy]   = 1;
                            }
                            if (display_type == 1)
                            {
                                if (((int)ranges_vertical[h] > 0) && ((int)ranges_vertical[h] < img_width))
                                {
                                    drawing.drawLine(img, img_width, img_height, (int)ranges_vertical[h], h, prev_x, prev_y, 0, 255, 0, 1, false);
                                }
                            }
                        }
                        prev_x = (int)ranges_vertical[h];
                        prev_y = h;
                    }
                }
            }

            //calculate average disparity
            int   hits         = 0;
            float av_disparity = 0;

            for (int w = img_width / 4; w < img_width - (img_width / 4); w++)
            {
                if (hits_horizontal[w] > 0)
                {
                    av_disparity += (ranges_horizontal[w] / scale);
                    hits++;
                }
            }
            if (hits > 0)
            {
                av_disparity /= hits;
            }
            if (av_disparity > 0)
            {
                av_disparity = 1.0f / av_disparity;
            }
            average_disparity = (average_disparity * 0.7f) + (av_disparity * 0.3f);

            if (display_type == 2)
            {
                for (int xx = 0; xx < img_width; xx++)
                {
                    if (hits_horizontal[xx] > 0)
                    {
                        for (int yy = 0; yy < img_height; yy++)
                        {
                            if (hits_vertical[yy] > 0)
                            {
                                int intensity = 255 - (int)((ranges_horizontal[xx] + ranges_vertical[yy]) * 255 / img_width);
                                if (intensity < 0)
                                {
                                    intensity = 0;
                                }
                                for (int col = 0; col < 3; col++)
                                {
                                    img[(((yy * img_width) + xx) * 3) + col] = (Byte)intensity;
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// update stereo feature tracking
        /// </summary>
        /// <param name="features">stereo features</param>
        /// <param name="img_width">image width</param>
        /// <param name="img_height">image height</param>
        public void update(stereoFeatures features,
                           int img_width, int img_height)
        {
            stereoFeatures prev_features = null;

            if (matched_index_list.Count == 0)
            {
                IDs = new sentienceTrackingFeature[history_steps, 1000];
                for (int h = 0; h < history_steps; h++)
                {
                    matched_index_list.Add(new int[1000]);
                    for (int i = 0; i < 1000; i++)
                    {
                        IDs[h, i] = null;
                    }
                }
            }

            int prev_step = curr_step - 1;

            if (prev_step < 0)
            {
                prev_step += history_steps;
            }
            int[] matched_indexes      = (int[])matched_index_list[curr_step];
            int[] prev_matched_indexes = (int[])matched_index_list[prev_step];

            if (prev_feature_list.Count > 1)
            {
                int prev_step2 = curr_step - 2;
                if (prev_step2 < 0)
                {
                    prev_step2 += history_steps;
                }

                prev_features = (stereoFeatures)prev_feature_list[prev_step];
                stereoFeatures prev_features2 = (stereoFeatures)prev_feature_list[prev_step2];

                // predict the positions of features using the velocity values
                for (int i = 0; i < prev_features.no_of_features; i++)
                {
                    if (IDs[prev_step, i] != null)
                    {
                        if ((IDs[prev_step, i].vx != 0) || ((IDs[prev_step, i].vy != 0)))
                        {
                            prev_features.features[(i * 3)]     = IDs[prev_step, i].predicted_x;
                            prev_features.features[(i * 3) + 1] = IDs[prev_step, i].predicted_y;
                        }
                    }
                }

                // match predicted feature positions with the currently observed ones
                features.match(prev_features, matched_indexes,
                               img_width, img_height,
                               max_displacement_x, max_displacement_y, true);

                // fill in any gaps

                features.match(prev_features2, prev_matched_indexes,
                               img_width, img_height,
                               max_displacement_x, max_displacement_y, true);


                for (int i = 0; i < features.no_of_features; i++)
                {
                    // if the feature has been matched with a previous one update its ID
                    if (matched_indexes[i] > -1)
                    {
                        IDs[curr_step, i] = IDs[prev_step, matched_indexes[i]];
                    }
                    else
                    {
                        if (prev_matched_indexes[i] > -1)
                        {
                            IDs[curr_step, i] = IDs[prev_step2, prev_matched_indexes[i]];
                        }
                        else
                        {
                            IDs[curr_step, i] = null;
                        }
                    }
                }
            }

            // update the persistence and average disparity for observed features
            for (int i = 0; i < features.no_of_features; i++)
            {
                int   x    = (int)features.features[i * 3];
                int   y    = (int)features.features[(i * 3) + 1];
                float disp = features.features[(i * 3) + 2];

                if (IDs[curr_step, i] != null)
                {
                    int dx = (int)(x - IDs[curr_step, i].predicted_x);
                    if (dx < 0)
                    {
                        dx = -dx;
                    }
                    IDs[curr_step, i].updatePosition(x, y);

                    float av_disparity = 0;
                    if (dx < 50)
                    {
                        // if the feature has not moved very much
                        IDs[curr_step, i].persistence++;
                        IDs[curr_step, i].total_disparity += disp;
                        av_disparity = IDs[curr_step, i].total_disparity / IDs[curr_step, i].persistence;
                    }
                    else
                    {
                        av_disparity = (IDs[curr_step, i].average_disparity * 0.9f) +
                                       (disp * 0.1f);
                    }

                    if (av_disparity > 0)
                    {
                        float disp_change     = (av_disparity - disp) / av_disparity;
                        float disp_confidence = 1.0f / (1.0f + (disp_change * disp_change));
                        int   idx             = matched_indexes[i];
                        if (idx > -1)
                        {
                            features.uncertainties[i] = prev_features.uncertainties[idx] -
                                                        ((prev_features.uncertainties[idx] * disp_confidence * uncertainty_gain));
                            if (features.uncertainties[i] < 0.2f)
                            {
                                features.uncertainties[i] = 0.2f;
                            }
                            features.uncertainties[i] *= 1.02f;
                            if (features.uncertainties[i] > 1)
                            {
                                features.uncertainties[i] = 1;
                            }
                        }
                    }

                    IDs[curr_step, i].average_disparity = av_disparity;
                    features.features[(i * 3) + 2]      = IDs[curr_step, i].average_disparity;
                }

                // create a new tracking feature
                if (IDs[curr_step, i] == null)
                {
                    IDs[curr_step, i] = new sentienceTrackingFeature(max_ID, x, y, disp);
                    max_ID++;
                    if (max_ID > 30000)
                    {
                        max_ID = 1;
                    }
                }
            }

            curr_step++;
            if (curr_step >= history_steps)
            {
                curr_step = 0;
            }
            if (prev_feature_list.Count < history_steps)
            {
                prev_feature_list.Add(features);
            }
            else
            {
                prev_feature_list[curr_step] = features;
            }
            //prev_features = features;
        }
Beispiel #7
0
        /// <summary>
        /// update the colour of each feature from the given image
        /// </summary>
        /// <param name="camera_index">stereo camera index</param>
        /// <param name="img">colour image</param>
        public void updateFeatureColours(int camera_index, byte[] img)
        {
            // get the dimensions of the colour image
            int wdth = calibration[camera_index].leftcam.image_width;
            int hght = calibration[camera_index].leftcam.image_height;

            for (int f = 0; f < features[camera_index].no_of_features; f++)
            {
                int            idx  = f * 3;
                stereoFeatures feat = features[camera_index];

                // get the coordinate of the feature within the image
                int x = (int)feat.features[idx];
                int y = (int)feat.features[idx + 1];

                // correct the positions using the inverse calibration lookup
                if (calibration[camera_index].leftcam.calibration_map_inverse != null)
                {
                    //int x2 = calibration[camera_index].leftcam.calibration_map_inverse[x, y, 0];
                    //int y2 = calibration[camera_index].leftcam.calibration_map_inverse[x, y, 1];
                    //x = x2;
                    //y = y2;
                }

                // update the colour for this feature
                // there's a little averaging here to help reduce noise
                if (x > wdth - 2)
                {
                    x = wdth - 2;
                }
                int n = ((y * wdth) + x) * 3;
                feat.colour[f, 2] = (byte)((img[n] + img[n + 3]) / 2);
                feat.colour[f, 1] = (byte)((img[n + 1] + img[n + 4]) / 2);
                feat.colour[f, 0] = (byte)((img[n + 2] + img[n + 5]) / 2);


                /*
                 * //testing colours
                 * int middle = x * hght / wdth;
                 * if (y > middle + (hght / 6))
                 * {
                 *  feat.colour[f, 2] = (Byte)255;
                 *  feat.colour[f, 1] = 0;
                 *  feat.colour[f, 0] = 0;
                 * }
                 * else
                 * {
                 *  if (y < middle - (hght / 6))
                 *  {
                 *      feat.colour[f, 2] = 0;
                 *      feat.colour[f, 1] = 0;
                 *      feat.colour[f, 0] = (Byte)255;
                 *  }
                 *  else
                 *  {
                 *      feat.colour[f, 2] = 0;
                 *      feat.colour[f, 1] = (Byte)255;
                 *      feat.colour[f, 0] = 0;
                 *  }
                 * }
                 */
            }
        }
Beispiel #8
0
 /// <summary>
 /// load stereo features for all cameras
 /// </summary>
 /// <param name="camera_index">stereo camera index</param>
 /// <param name="feat">stereo camera features</param>
 public void setStereoFeatures(int camera_index, stereoFeatures feat)
 {
     features[camera_index] = feat;
 }