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
{
  public:
    //! 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;
            
            timer.start();
      // 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));
                    if(colour.val[0]==255)
                    {
                        rightEdge[j] = i;
                    }
                    colour = thresholdimg.at<uchar>(cv::Point(roi.width - i, j));
                    if(colour.val[0]==255)
                    {
                        leftEdge[j] = roi.width - i;
                    }
                    //count white pixels
                    colour = thresholdimg.at<uchar>(cv::Point(roi.width - i, j));
                    if(colour.val[0]==255)
                    {
                        whitePixels++;
                    }
                }
            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:
            inframe.done();
      // 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:
      draw_fut.get();
            //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:
JEVOIS_REGISTER_MODULE(linefind);