FRCVision Example Help

To the minds of CD, help me out here. Yesterday in our build day one of our students and I were trying to use the Raspberry Pi as a co-processor, following the frcvision steps. We get everything going just fine I think. Then, to show him the next couple steps my goal was to download the example, modify it to grab the image, draw a circle in the middle of the image and put the new processed image into the MJPG stream.

In years past, we have been able to simply grab the Mat, do our filtering, and toss the mat on to a CvSource object and Bob’s your uncle everything is working. This is not however working for me.

After downloading the example, the only modification I made was the following:

  public static class MyPipeline implements VisionPipeline {
    public int val;
    CvSource outputStream = CameraServer.getInstance().putVideo("Circle", 320, 240);

    @Override
    public void process(Mat mat) {
      Imgproc.circle(mat, new Point(160, 120), 15, new Scalar(0,0,255));

      outputStream.putFrame(mat);
    }
  }

This example project builds just fine, and I can successfully upload it to the Pi and re-open a camera stream.

What I can’t figure out is how to have the MJPG stream show my modified image with the circle. I know I’m missing something terribly obvious, but I’d really like to get this proof-of-concept into my student’s hands so he can get moving on completing our targeting for this year.

Thanks everyone (in advance).

Don’t modify the mat passed in. Create a separate mat and do the circle operation with the passed-in mat as the source and the separate mat as the destination. Then putFrame() the separate mat.

The problem is that the passed-in mat is reused for the next frame, creating a race condition between getting another frame and putting the modified frame.

So like this:

@Override
    public void process(Mat mat) {
      Mat outMat = mat;
      Imgproc.circle(outMat, new Point(160, 120), 15, new Scalar(0,0,255));

      outputStream.putFrame(outMat);
    }

If I do it that way, I haven’t figured out exactly what the new MJPG stream URL will be. I’ve always used the SmartDashboard in vision stuff in the past with our team, and we’ve always easily found the new streams by name in the SmartDashboard. I tried http://pi ip address/Circle.mjpg (as I thought I was naming the output mjpg stream “circle” but that doesn’t return any data.

Like this:

  public static class MyPipeline implements VisionPipeline {
    public int val;
    CvSource outputStream = CameraServer.getInstance().putVideo("Circle", 320, 240);
    Mat outputMat = new Mat();

    @Override
    public void process(Mat mat) {
      mat.copyTo(outputMat);
      Imgproc.circle(outputMat, new Point(160, 120), 15, new Scalar(0,0,255));

      outputStream.putFrame(outputMat);
    }
  }

Regarding the stream URL, it uses incrementing port numbers, starting from 1181. So it would still be stream.mjpg, just on port 1182 (or 1183, etc). Dashboards find the stream URLs via NetworkTables (where CameraServer publishes the stream info).

Turns out it was working, I think explicitly instantiating and calling copyTo is the best way to teach the students so I’ll make the change.

I just didn’t realize the ports increment, so now I see it.png

Thanks so much for your contributions here on CD. I have learned a lot from your posts, which in turn has passed a lot of knowledge on to our kids which is why we really do this…so thanks again.