Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Inline undistorting an image

Hello,

I have used the OpenCV Calibration functions to create my distortion coefficients along with the camera matrix. Now, I want to take the distortion coefficients along with camera matrix to undistort a specific columns and rows in a random fashion. The reason for this is that I take the original distorted imagine and calculate a single line of columns such that I take all pixel values in a given column to arrive at a specific row weighted average.

From this, I want to remove the distortion of just this single line of X and Y(values). What specific calculation do I need to do to get this undistorted result? I don't need to go back to image pixel space, therefore everything can remain in floating point. I have tried the following, however I believe is production the distorted values because the resulting curve is in the wrong direction.

Find code snippet below: I used the equation that is contained in initundistortrectifymap removing the rectify aspects and unsuded K3,k4,5 and such.

void __fastcall TCamera::ProcessImage(mvIMPACT::acquire::ImageBuffer * ABuffer) { //Member function accepts an input image buffer and calculates a measure buffer //The measure buffer is width42, where each column contains both an row //sum average and a sum intensity. TBufferFrame * LBuffer;

double LDistortedX,LDistortedY;
//Distortion removal elements
double Lx;
double Ly;
double Lxy;
double LSqrX;
double LSqrY;
double LSqrD;       //Square Distance (^2) also known as r2
double LSqrSqrD;    //Distance (^4)
double LDestX;
double LDestY;
double LInvDen;
double Lkr;
double Lp1,Lp2;
double Lk1,Lk2;
double Lu0,Lv0;
double Lfx,Lfy;

unsigned __int32 LRowOffset;
unsigned __int32 LRow;
unsigned __int32 LColumn;
unsigned __int32 LWidth;
unsigned __int32 LHeight;
unsigned __int32 LOffset;
unsigned __int32 LXSum;
unsigned __int32 LIntensity;
unsigned __int32 LData;

union
{
    void * LRawData;
    unsigned __int8 * LByteData;
    unsigned __int16 * LWordData;
    unsigned __int32 * LDwordData;
};

if(ABuffer!=NULL)
{
    LXSum = 0;
    LIntensity = 0;
    LRowOffset = ABuffer->iWidth;
    LWidth = ABuffer->iWidth;
    LHeight = ABuffer->iHeight;


    LBuffer = FFrameManager->NewFrame(FFrameId);
    if(LBuffer==nullptr)
        return;

    LRawData = ABuffer->vpData;

    Lk1 = FLensModel.R[0];  //Radial coefficient 1 (k1)
    Lk2 = FLensModel.R[1];  //Radial coefficient 2 (k2)
    Lp1 = FLensModel.T[0];  //Tangental coefficient 1 (p1)
    Lp2 = FLensModel.T[1];  //Tangental coefficient 2 (p2)
    Lu0 = FLensModel.Center[0]; //Optical center X
    Lv0 = FLensModel.Center[1]; //Optical center y
    Lfx = FLensModel.Fx;    //Camera Focal Fx
    Lfy = FLensModel.Fy;    //Camera Focal Fy

    //First,calculate column data as XSum and Intensity.
    for(LColumn=0;LColumn<LWidth;LColumn++)
    {
        LXSum = 0;
        LIntensity = 0;

        for(LRow=0;LRow<LHeight;LRow++)
        {
            //Assume data is mono8 for now.
            LOffset = LRowOffset*LRow + LColumn;
            LData = LByteData[LOffset];
            if(LData>10)    //Threshold of 10
            {
                LXSum += (LRow+1)*LData;
                LIntensity += LData;
            }
        }

        //Now, calibration the result and put into the measure record.
        if(LIntensity<50)
        {
            LBuffer->Data[LColumn].Range = 0;
            LBuffer->Data[LColumn].X = 0;
        }
        else
        {
            //Calculate the range and x.
            LDistortedX = LColumn;
            LDistortedY = (double)LXSum/(double)LIntensity;

            Lx = (LDistortedX - Lu0)/Lfx;
            Ly = (LDistortedY - Lv0)/Lfy;
            Lxy = Lx*Ly;
            LSqrX = Lx*Lx;
            LSqrY = Ly*Ly;
            LSqrD = LSqrX+LSqrY;
            LSqrSqrD = LSqrD*LSqrD;
            Lkr = (1.0l +((0*LSqrD + Lk2)*LSqrD + Lk1)*LSqrD);
            LDestX = Lfx*(Lx*Lkr + Lp1*2.0l*Lxy + Lp2*(LSqrD + 2.0l*LSqrX)) + Lu0;
            LDestY = Lfy*(Ly*Lkr + Lp1*(LSqrD + 2.0l*LSqrY) + Lp2*2.0l*Lxy) + Lv0;

            LBuffer->Data[LColumn].X = LDestX;  //undistorted column/row data
            LBuffer->Data[LColumn].Range = LDestY; //undistorted column/row data
        }
    }

    if(FFrameManager->FrameCount==FBufferHeight)
    {
        //Now, stream it
        LData = FFrameManager->FrameCount;
        if(FOnStreamBuffer!=nullptr)
            FOnStreamBuffer(this);
        FFrameManager->Clear();
    }
}

}

Inline undistorting an image

Hello,

I have used the OpenCV Calibration functions to create my distortion coefficients along with the camera matrix. Now, I want to take the distortion coefficients along with camera matrix to undistort a specific columns and rows in a random fashion. The reason for this is that I take the original distorted imagine and calculate a single line of columns such that I take all pixel values in a given column to arrive at a specific row weighted average.

From this, I want to remove the distortion of just this single line of X and Y(values). What specific calculation do I need to do to get this undistorted result? I don't need to go back to image pixel space, therefore everything can remain in floating point. I have tried the following, however I believe is production the distorted values because the resulting curve is in the wrong direction.

Find code snippet below: I used the equation that is contained in initundistortrectifymap removing the rectify aspects and unsuded K3,k4,5 and such.

void __fastcall TCamera::ProcessImage(mvIMPACT::acquire::ImageBuffer * ABuffer)
{
//Member function accepts an input image buffer and calculates a measure buffer
//The measure buffer is width42, width*4*2, where each column contains both an row
//sum average and a sum intensity.
TBufferFrame * LBuffer;

LBuffer;
double LDistortedX,LDistortedY;
 //Distortion removal elements
 double Lx;
 double Ly;
 double Lxy;
 double LSqrX;
 double LSqrY;
 double LSqrD; //Square Distance (^2) also known as r2
 double LSqrSqrD; //Distance (^4)
 double LDestX;
 double LDestY;
 double LInvDen;
 double Lkr;
 double Lp1,Lp2;
 double Lk1,Lk2;
 double Lu0,Lv0;
 double Lfx,Lfy;
 unsigned __int32 LRowOffset;
 unsigned __int32 LRow;
 unsigned __int32 LColumn;
 unsigned __int32 LWidth;
 unsigned __int32 LHeight;
 unsigned __int32 LOffset;
 unsigned __int32 LXSum;
 unsigned __int32 LIntensity;
 unsigned __int32 LData;
 union
 {
  void * LRawData;
  unsigned __int8 * LByteData;
 unsigned __int16 * LWordData;
 unsigned __int32 * LDwordData;
 };
 if(ABuffer!=NULL)
 {
 LXSum = 0;
 LIntensity = 0;
 LRowOffset = ABuffer->iWidth;
 LWidth = ABuffer->iWidth;
 LHeight = ABuffer->iHeight;
 LBuffer = FFrameManager->NewFrame(FFrameId);
 if(LBuffer==nullptr)
 return;
 LRawData = ABuffer->vpData;
  Lk1 = FLensModel.R[0]; //Radial coefficient 1 (k1)
 Lk2 = FLensModel.R[1]; //Radial coefficient 2 (k2)
 Lp1 = FLensModel.T[0]; //Tangental coefficient 1 (p1)
 Lp2 = FLensModel.T[1]; //Tangental coefficient 2 (p2)
 Lu0 = FLensModel.Center[0]; //Optical center X
 Lv0 = FLensModel.Center[1]; //Optical center y
 Lfx = FLensModel.Fx; //Camera Focal Fx
 Lfy = FLensModel.Fy; //Camera Focal Fy
  //First,calculate column data as XSum and Intensity.
 for(LColumn=0;LColumn<LWidth;LColumn++)
 {
 LXSum = 0;
 LIntensity = 0;
 for(LRow=0;LRow<LHeight;LRow++)
 {
  //Assume data is mono8 for now.
 LOffset = LRowOffset*LRow + LColumn;
 LData = LByteData[LOffset];
  if(LData>10) //Threshold of 10
 {
  LXSum += (LRow+1)*LData;
 LIntensity += LData;
 }
 }
  //Now, calibration the result and put into the measure record.
 if(LIntensity<50)
 {
 LBuffer->Data[LColumn].Range = 0;
 LBuffer->Data[LColumn].X = 0;
 }
 else
 {
  //Calculate the range and x.
 LDistortedX = LColumn;
 LDistortedY = (double)LXSum/(double)LIntensity;
  Lx = (LDistortedX - Lu0)/Lfx;
 Ly = (LDistortedY - Lv0)/Lfy;
 Lxy = Lx*Ly;
 LSqrX = Lx*Lx;
 LSqrY = Ly*Ly;
 LSqrD = LSqrX+LSqrY;
 LSqrSqrD = LSqrD*LSqrD;
  Lkr = (1.0l +((0*LSqrD + Lk2)*LSqrD + Lk1)*LSqrD);
  LDestX = Lfx*(Lx*Lkr + Lp1*2.0l*Lxy + Lp2*(LSqrD + 2.0l*LSqrX)) + Lu0;
 LDestY = Lfy*(Ly*Lkr + Lp1*(LSqrD + 2.0l*LSqrY) + Lp2*2.0l*Lxy) + Lv0;
 LBuffer->Data[LColumn].X = LDestX; //undistorted column/row data
  LBuffer->Data[LColumn].Range = LDestY; //undistorted column/row data
 }
 }
 if(FFrameManager->FrameCount==FBufferHeight)
 {
  //Now, stream it
 LData = FFrameManager->FrameCount;
 if(FOnStreamBuffer!=nullptr)
 FOnStreamBuffer(this);
 FFrameManager->Clear();
 }
 }
}

}