How to use cameras for ranging (opencv)
Author: Guo shilong
I have been busy looking for a job recently, and my blog is always full of grass. Today, let's put a previous job on it to fill the facade. I remember where I saw this stuff made by a foreigner. I thought it was fun and I made it myself. A laser pointer is fixed under the camera to form a simple ranging device. Check it out.
Principle
Assuming that the laser beam is completely parallel to the optical axis of the camera, the center of the laser beam is the brightest point in the camera's sight. When a laser beam is directed to the tracking target in the camera's field of view, the camera can capture this point. Through simple image processing methods, the most bright spots of laser beam formation can be found in the investigation image, at the same time, you can calculate the number of pixels from the top of the Y axis to the image center. The closer the point is to the center of the image, the farther the object to be tested is from the robot. The distance from the graph can be calculated. D:
(1)
In the equation, H is a constant, which is the vertical distance between the camera and the laser transmitter and can be directly measured.
θ can be calculated using the following formula: θ = num * ROP + offset (2) where: num is the number of pixels from the center of the image to the point of landing. Drop is the radian value offset of each pixel. The following equation can be obtained: (3) num can be calculated from the image. The ROP and offset values must be calculated through experiments. First, the exact value of D is measured, and then the exact θ can be calculated based on equation (1). According to equation (2), the equations containing only the parameters drop and offset can be obtained. Calculate θ for the exact value of D measured multiple times at different distances. The equations can be used to obtain the ROP and offset values. Here, ROP = 0.0030354, offset = 0.056514344.
ProgressHeader file: Class laserrange
{
Public:
Struct rangeresult * getrange (iplimage * imgrange, iplimage * imgdst );
Laserrange ();
Virtual ~ Laserrange ();
PRIVATE:
Unsigned int maxw;
Unsigned int maxh;
Unsigned int maxpixel;
Rangeresult * strctresult;
// Values used for calculating range from captured image data
Const double gain; // gain constant used for converting pixel offset to angle in radians
Const double offset; // offset constant
Const double h_cm; // distance between center of camera and laser
Unsigned int pixels_from_center; // brightest pixel location from Center
Void preprocess (void * IMG, iplimage * imgtemp );
}; CPP file: laserrange (): gain (0.0030354), offset (0), h_cm (4.542)
{
Maxw = 0;
Maxh = 0;
Maxpixel = 0;
Pixels_from_center = 0; // brightest pixel location from center strctresult = new rangeresult;
Strctresult-> maxcol = 0;
Strctresult-> maxrow = 0;
Strctresult-> maxpixel = 0;
Strctresult-> range = 0.0;
} Laserrange ::~ Laserrange ()
{
If (null! = Strctresult) delete strctresult;
} Struct rangeresult * laserrange: getrange (iplimage * imgrange, iplimage * imgdst)
{
If (null = imgrange) return strctresult;
Preprocess (imgrange, imgdst );
Pixels_from_center = ABS (120-maxh); // Calculate range in cm based on bright pixel location, and setup specific Constants
Strctresult-> range = h_cm/TAN (pixels_from_center * gain + offset );
Strctresult-> pixfromcent = pixels_from_center;
Strctresult-> maxcol = maxw;
Strctresult-> maxrow = maxh;
Strctresult-> maxpixel = maxpixel;
// Strctresult-> range = 0.0;
Return strctresult;
} Void laserrange: preprocess (void * IMG, iplimage * imgtemp)
{
Maxpixel = 0; // The maximum pixel value before the next frame is cleared;
Iplimage * image = reinterpret_cast <iplimage *> (IMG );
Cvcvtpixtoplane (image, 0, 0, imgtemp, 0 );
For (Int J = (imgtemp-> width-60)/2-1); j <(imgtemp-> width-40)/2 + 59; j ++)
{
For (INT I = 5; I height-5; I ++)
{
If (imgtemp-> imagedata [I * imgtemp-> widthstep + J])> maxpixel)
{
If (imgtemp-> imagedata [(I-1) * imgtemp-> widthstep + J])> maxpixel) & (imgtemp-> imagedata [(I-1) * imgtemp-> widthstep + J + 1])> maxpixel & (imgtemp-> imagedata [(I-1) * imgtemp-> widthstep + J-1 ))
{
If (imgtemp-> imagedata [(I + 1) * imgtemp-> widthstep + J])> maxpixel) & (imgtemp-> imagedata [(I + 1) * imgtemp-> widthstep + J + 1])> maxpixel & (imgtemp-> imagedata [(I + 1) * imgtemp-> widthstep + J-1]> maxpixel ))
{
If (imgtemp-> imagedata [I * (imgtemp-> widthstep) + J + 1])> maxpixel)
{
If (imgtemp-> imagedata [I * (imgtemp-> widthstep) + J-1])> maxpixel)
{
Maxpixel = imgtemp-> imagedata [I * imgtemp-> widthstep + J];
Maxw = J;
Maxh = I;
}
}
}
}
}
}
} Call the function: int claservisiondlg: captureimage ()
{
// Cvcapture * capture = 0;
// Capture = cvcapturefromcam (0); // 0 indicates the device number.
If (! Capture)
{
Fprintf (stderr, "cocould not initialize capturing.../N ");
Return-1;
}
// Cvnamedwindow ("laserrangeimage", 1 );
// Cvvnamedwindow ("image", 1 );
Cvvnamedwindow ("dimage", 1 );
For (;;)
{
Iplimage * frame = 0;
If (isstop) break; frame = cvqueryframe (capture); // capture an image frame from the camera
If (! Frame)
Break; If (! Imgorign)
{
// Allocate all the buffers
Imgorign = cvcreateimage (cvgetsize (FRAME), 8, 3); // create an image
Imgorign-> origin = frame-> origin;
} Cvcopy (frame, imgorign, 0); // copy the image frame to the image
// Cvshowimage ("laserrangeimage", imgorign );
If (! Imgdest)
{
Imgdest = cvcreateimage (cvsize (imgorign-> width, imgorign-> height), 8, 1 );
Cvzero (imgdest );
}
Struct rangeresult * temp = laservsion. getrange (imgorign, imgdest );
Cvline (imgorign, cvpoint (temp-> maxcol, 0), cvpoint (temp-> maxcol, imgorign-> height), cvscalar (100,100,255, 0), 0 );
Cvline (imgorign, cvpoint (0, temp-> maxrow), cvpoint (imgorign-> width, temp-> maxrow), cvscalar (100,100,255, 0), 0 );
// Cvvshowimage ("image", imgorign );
Cvsaveimage ("image.bmp", imgorign );
Cvvshowimage ("dimage", imgdest );
// Display the image on picturebox
CDC * PDC = getdlgitem (idc_picture)-> getdc ();
CDC dcmemory;
Bitmap bm;
Dcmemory. createcompatibledc (PDC );
Cbitmap * pbmp;
Cstring szfilename = "image.bmp ";
Hbitmap HBK = (hbitmap): LoadImage (null, szfilename, image_bitmap, 0, 0, lr_loadfromfile );
If (null! = HBK)
{
Pbmp = cbitmap: fromhandle (HBK );
Pbmp-> GetObject (sizeof (Bitmap), & BM );
Dcmemory. SelectObject (pbmp );
PDC-> bitblt (0, 0, BM. bmwidth, BM. bmheight, & dcmemory, 0, 0, srccopy );}
Char STR [80]; // To Print message
CDC * PDCP = getdc ();
Char str2 [80];
// Display frame coordinates as well as calculated range
Sprintf (STR, "pix max value = % d at x = % u, y = % u, pixfromcent = % d", temp-> maxpixel, temp-> maxcol, temp-> maxrow, temp-> pixfromcent );
Sprintf (str2, "range = % F cm", temp-> range );
PDCP-> textout (30, 33, STR );
PDCP-> textout (50, 50, str2 );
Releasedc (PDCP );
Int c = cvwaitkey (10 );
// If (C = 'q ')
// Break;
} // Cvreleasecapture (& capture );
// Cvdestroywindow ("laserrangeimage ");
// Cvdestroywindow ("image ");
Cvdestroywindow ("dimage ");
Return 0;
} If you need a project file, leave the email address
Hard work and happy life