5

I am working with an IDS camera with wide fish-eye. It is 2D-camera, but I need just the line in the middle. I got how to calibrate the camera: I can get undistorted images.

My problem is that I need quick computation. So I'm trying to find a way, how to compute just a crop, and not whole picture, and then crop. I need something like this:

Picture.

I have tried this, but it did not helped me.

Is there any way to compute just a crop (1280x6) and not all picture (1280x960)?

int main ()
{
   timespec time1, time2, timeAfterS, timeStart, execTime;
   Mat intrinsic = Mat (3, 3, CV_32FC1);
   Mat newCamMat=Mat (3, 3, CV_32FC1);
   Mat distCoeffs;
   FileStorage fs ("cameraData.xml", FileStorage::READ);
   fs["intrinsic"] >> intrinsic;
   fs["distCoeffs"] >> distCoeffs;
   fs.release ();
   VideoCapture capture = VideoCapture (0);


   Mat image;
   Mat imageUndistorted;
   int l = 0;
   clock_gettime (CLOCK_REALTIME, &timeStart);

   //For Example i need to compute just this following crop of image
   //    |
   //    V
   Rect recT(10,10,20,20);
   while (l != 27)
   {

      capture >> image;
      newCamMat=getOptimalNewCameraMatrix (intrinsic, distCoeffs,  
                      image.size(),0.5,image.size(),&recT,false);
      newCamMat.at<double>(0,2)=0;
      newCamMat.at<double>(1,2)=20;
      undistort (image, imageUndistorted, intrinsic,   
                              distCoeffs,newCamMat);

      imshow ("win1", image);
      imshow ("win2", imageUndistorted);
      l = waitKey (1);

  }

  capture.release ();
  return 0;
}

Thank you ahead,

Anton

Update: I think I found some solution, but I did not have an opportunity yet to work it out properly. It seems to be working. So the Idea is: In my CameraMatrix cx and cy are the points of "center of liens". For example it lays on the middle of my ROI(let it be 200,200). My ROI is (0,180,400,220).I cut ROI out and first shift center of camera to my new center. Because now my ROI is now (0,0,400,40). My cx stays 200, but cy has to be shifted to 20. Then I change in initUndistortRectifyMap size according my cropsize. And then i can put in "remap" already my crop picture. Code follows below.

#include <iostream>
#include "opencv2/opencv.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <sstream>
#include <ctime>
#include <time.h>
#include <cmath>
using namespace cv;
using namespace std;

timespec diff (timespec start, timespec end)
{
    timespec temp;
    if ((end.tv_nsec - start.tv_nsec) < 0)
    {
        temp.tv_sec = end.tv_sec - start.tv_sec - 1;
        temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
    }
    else
    {
        temp.tv_sec = end.tv_sec - start.tv_sec;
        temp.tv_nsec = end.tv_nsec - start.tv_nsec;
    }
    return temp;
}
int main ()
{
    timespec time1, time2, timeAfterS, timeStart, execTime;
    Mat intrinsic = Mat (3, 3, CV_32FC1);
    Mat newCamMat = Mat (3, 3, CV_32FC1);
    Mat distCoeffs;
    FileStorage fs ("cameraData.xml", FileStorage::READ);
    fs["intrinsic"] >> intrinsic;
    fs["distCoeffs"] >> distCoeffs;
    fs.release ();
    intrinsic.copyTo(newCamMat);
    VideoCapture capture = VideoCapture (0);
    capture.set (CAP_PROP_FPS, 90);
    Mat image;
    Mat imageUndistorted;
    Mat imageUndistorted1;
    int l = 0;
    capture >> image;
    clock_gettime (CLOCK_REALTIME, &timeStart);
    Rect recT (10, 10, 20, 20);
    Rect roi (0, 400, 640, 30);//Region of Interests
    Rect roi1 (0, 360, 640, 60); // To show borders of ROI
    Mat view, rview, map1, map2,map3,map4,crop2;
    Mat crop = Mat (30, 640, CV_8UC3); // here I define the size of crop
    intrinsic.at<double> (1, 2) = intrinsic.at<double> (1, 2) - 400; // here i shift the cy to the new middle of frish cut ROI
initUndistortRectifyMap (intrinsic, distCoeffs, Mat (), intrinsic, crop.size (), CV_16SC2, map1, map2); // here i apply transform.. at least i believe i do it :)
while (l != 27)
{
    capture >> image;
    rectangle (image, recT, Scalar (255, 0, 0), 2, 8, 0);
    rectangle (image, roi, Scalar (255, 0, 0), 2, 8, 0);
    clock_gettime (CLOCK_REALTIME, &time1);
    remap (image(roi), imageUndistorted, map1, map2, INTER_LINEAR);

    initUndistortRectifyMap (newCamMat, distCoeffs, Mat (),  
    newCamMat, image.size (), CV_16SC2, map3, map4);// to compare with uncroped picture
    remap (image, imageUndistorted1, map3, map4, INTER_LINEAR);

    clock_gettime (CLOCK_REALTIME, &time2);
    execTime = diff (time1, time2);
        cout << "  FPS: " << 1000000000. / execTime.tv_nsec << " per second, " << endl;
    imshow("image(roi)",image(roi1));
    imshow ("win1", image);
    imshow ("win2", imageUndistorted);
    imshow ("win3", imageUndistorted1);
    l = waitKey (1);
}
capture.release ();
return 0;

}

Community
  • 1
  • 1
Anton
  • 61
  • 6
  • 3
    instead of using the function "undistort" you can use two functions: 1. precompute the undistortion map only once (function called inotUndistortRectifyMap) 2. for each image: Just apply the map. If that is still not fast enough, find out how you can apply only the relevant part of such a map. – Micka Apr 27 '17 at 22:50
  • I thought about take the functions from OpenCV source code, and change them somehow. There anyway have to be "for(int i=some element;i – Anton Apr 28 '17 at 09:28
  • it your camera intrinsics and distortion dont change, just change the remap. If they change, you have to compute the map over and over and probably should optimize it, too – Micka Apr 28 '17 at 09:42
  • I'll try and post the results. Thanks for advice! – Anton Apr 28 '17 at 12:06
  • I think i found some solution, but I did not have an opportunity yet to work it out properly. It seems to be working. So the Idea is: In my CameraMatrix cx and cy are the points of "center of liens". For example it lays on the middle of my ROI(let it be 200,200). My ROI is (0,180,400,220).I cut ROI out and first shift center of camera to my new center. Because now my ROI is now (0,0,400,40). My cx stays 200, but cy has to be shifted to 20. Then I change in initUndistortRectifyMap size according my cropsize. And then i can put in "remap" already my crop picture. Code follows below. – Anton Apr 28 '17 at 22:58
  • might work! I'm not that deep into lens distortion, but it sounds ok. Should be easily verifiable – Micka Apr 28 '17 at 23:00
  • Rect recT (10, 10, 20, 20); Rect roi (0, 400, 640, 30); Mat view, rview, map1, map2,crop2; Mat crop = Mat (30, 640, CV_8UC3); // here I define the size of crop intrinsic.at (1, 2) = intrinsic.at (1, 2) - 475; // here i shift the crop to the middle, my cy is 490 initUndistortRectifyMap (intrinsic, distCoeffs, Mat (), intrinsic, crop.size (), CV_16SC2, map1, map2); // here i apply transform.. at least i believe i do it :) capture >> image; remap (image(roi), imageUndistorted, map1, map2, INTER_LINEAR);
     
    – Anton Apr 28 '17 at 23:04
  • Does this answer your question? [OpenCV camera calibration of an image crop (ROI submatrix)](https://stackoverflow.com/questions/22437737/opencv-camera-calibration-of-an-image-crop-roi-submatrix) – cbuchart Jun 25 '20 at 06:54
  • Yep. It helped a lot. – Anton Jun 25 '20 at 10:44

0 Answers0