Welcome new user! You can search existing questions and answers without registering, but please register to post new questions and receive answers. Note that due to large amounts of spam attempts, your first three posts will be manually moderated, so please be patient.
Because of un-manageable amounts of spam despite our use of CAPTCHAs, email authorization, and other tools, we have discontinued this forum (see the 700k+ registered users with validated email addresses at right?). Please email us any questions or post bug reports and feature requests on GitHub at https://github.com/jevois -- The content below remains available for future reference.
Welcome to JeVois Tech Zone, where you can ask questions and receive answers from other members of the community.

Showing text from SaveVideo module in my own module when running on host

0 votes
I have written a module called linefind. It works but there are some strange behaviour.

When running on host through jevois-deamon, I get the text "SaveVideo: not recordning" on the output image. I don't write that anywhere in my code. How can it come from another module into mine?

I'm also drawing some dots, but they don't get erased in each frame. Is the image from outframe.get() not blank?

I'm using Jevois 1.8.0 on Ubunto 16.04.

My code is here:

// Linefind

#include <jevois/Core/Module.H>
#include <jevois/Image/RawImageOps.H>

#include <jevois/Debug/Timer.H>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <jevois/Debug/Log.H>
#include <linux/videodev2.h>
#include <jevois/Util/Utils.H>
#include <jevois/Util/Coordinates.H>

//#include <string.h>

    @author Kim Clausen
    @videomapping YUYV 320 480 30 YUYV 320 240 30 kimc linefind
    @email junktilkim@gmail.com
    @restrictions None

class linefind : public jevois::Module
    //! Default base class constructor ok
    using jevois::Module::Module;

    //! Virtual destructor for safe inheritance
    virtual ~linefind() { }

    //! Processing function
    virtual void process(jevois::InputFrame && inframe, jevois::OutputFrame && outframe) override
      static jevois::Timer timer("processing");//, 60, LOG_DEBUG);

      // Wait for next available camera image:
      jevois::RawImage const inimg = inframe.get(true);
            unsigned int const  w = inimg.width;
            unsigned int const  h = inimg.height;

      // We only support YUYV pixels in this example, any resolution:
      inimg.require("input", w, h, V4L2_PIX_FMT_YUYV);
      // Region of interest
      cv::Rect roi(20,h-100,w-40,80);

            // Convert to OpenCV grayscale:
            cv::Mat cvimg = jevois::rawimage::convertToCvGray(inimg);

            // Grey    
            cv::Mat grayimg = cvimg(roi);    

            // Blur image
            cv::Mat blurimg;
            cv::GaussianBlur(grayimg, blurimg, cv::Size(3, 3), 8);

            // Threshold
            cv::Mat thresholdimg;
            int retVal = cv::threshold(blurimg, thresholdimg, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);        
            // Edge detection
            int rightEdge[roi.height];
            int leftEdge[roi.height];
            int width[roi.height];
            int rightEdgeAvg = 0;
            int leftEdgeAvg = 0;
            int whitePixels = 0;

            for (int j=0; j<roi.height; j++)
                rightEdge[j] = 0;
                leftEdge[j] = 0;
                for (int i=0; i<roi.width; i++)
                    cv::Scalar colour = thresholdimg.at<uchar>(cv::Point(i, j));
                        rightEdge[j] = i;
                    colour = thresholdimg.at<uchar>(cv::Point(roi.width - i, j));
                        leftEdge[j] = roi.width - i;

                    //count white pixels
                    colour = thresholdimg.at<uchar>(cv::Point(roi.width - i, j));

            rightEdgeAvg += rightEdge[j];
            leftEdgeAvg += leftEdge[j];

                width[j] = rightEdge[j] - leftEdge[j];


            rightEdgeAvg = int(rightEdgeAvg / roi.height);
            leftEdgeAvg = int(leftEdgeAvg / roi.height);
      // Wait for an image from our gadget driver into which we will put our results:
      jevois::RawImage outimg = outframe.get();
            // Enforce the correct output image size and format:
            outimg.require("output", w, h * 2, inimg.fmt);

            // Paste original image
      //jevois::rawimage::paste(inimg, outimg, 0, 0);

            // Let camera know we are done processing the raw YUV input image:

      // Asynchronously launch a bunch of drawings
      auto draw_fut =
        std::async(std::launch::async, [&]() {

                    // Draw text
                  jevois::rawimage::writeText(outimg, "Line Finder", 3, 3, jevois::yuyv::White);

                    // Draw region of interest
                    jevois::rawimage::drawRect(outimg, roi.x, roi.y, roi.width, roi.height, jevois::yuyv::White);

                    // Output images
                    jevois::rawimage::pasteGreyToYUYV(cvimg, outimg, 0, inimg.height);
                    jevois::rawimage::pasteGreyToYUYV(thresholdimg, outimg, roi.x, h + roi.y);

                    //draw detected edges
                    for (int j=0; j<roi.height; j++)
                        jevois::rawimage::drawDisk(outimg, roi.x + rightEdge[j], roi.y + j, 1, jevois::yuyv::LightGreen);
                        jevois::rawimage::drawDisk(outimg, roi.x + leftEdge[j],  roi.y + j, 1, jevois::yuyv::LightPink);
                    //draw detected edges average
                    jevois::rawimage::drawDisk(outimg, roi.x + rightEdgeAvg, roi.y + roi.height/2, 5, jevois::yuyv::LightGreen);
                    jevois::rawimage::drawDisk(outimg, roi.x + leftEdgeAvg,  roi.y + roi.height/2, 5, jevois::yuyv::LightPink);


            // Wait for all drawings to complete:

            //sendSerial("L " + std::to_string(rightEdgeAvg) + " " + std::to_string(leftEdgeAvg) + " " +  std::to_string(retVal) + " " +  std::to_string(whitePixels));

      // Send the output image with our processing results to the host over USB:
      outframe.send(); // NOTE: optional here, outframe destructor would call it anyway

// Allow the module to be loaded as a shared object (.so) file:
asked Apr 4, 2018 in Programmer Questions by junktilkim (140 points)

1 Answer

0 votes

For why you see the SaveVideo text, this is because jevois-daemon on host requests a video resolution from the camera that corresponds to running SaveVideo inside the jevois camera. This will go away if either 1) you run jevois-daemon on host with a dumb camera instead of jevois, or 2) you install your module to the microSD of jevois and then just run guvcview or other dumb video capture on host. Please see here for more details:


section about "Host and Platform Modes"

Yes, outframe comes from a small set of pre-allocated buffers with direct memory access enabled for fast transfer over USB. The buffers are recycled. So you should assume that they contain random junk (usually they will indeed contain a previous output frame).

Maybe just uncomment this in you rmodule:

            // Paste original image
      //jevois::rawimage::paste(inimg, outimg, 0, 0);

or, if you just want a blank output, you can do a jevois::rawimage::drawFilledRect() over the whole output image (or a memset() over outimg->pixels() might be slightly faster but will give you solid green in YUYV).

Nice module, please post a video of your robot in action when you get it finalized!

answered Apr 4, 2018 by jvroot (360 points)