Victor Image Processing Library How-to Tips

Pattern Recognition, Find a Mark in an Image

To find a specific mark in an image we use statistical correlation to compare a reference image that defines the mark to a test image that may contain the mark. The result image is filled with the correlation coefficient data. The pixel in the result image with the highest value is the most probable location for the mark.

This procedure supports grayscale images. Use the Victor Library conversion functions to convert color or black and white images to 8-bit grayscale.

In general, the steps are:

source image pattern recognition image containing the pattern result image pattern recognition
Test image Reference image Result image, mark found at (84, 213)

The result image is filled with pixel data that represent the correlation coefficient calculated between the reference image and the test image at each pixel location. The pixel values can range from zero (negative correlation) through 128 (no correlation) up to 255 (perfect positive correlation). A negative correlation would mean a good match with the negative image of the reference mark.

The brightest pixel in the result image represents the most probable location of the reference mark. In this case that is at location (84, 213).


VB.NET Source Code | C# Source Code
VB Source Code | C/C++ Source Code


Find a Mark - the VB.NET Source Code

Requires Victor Image Processing Library for 32-bit Windows v 6.0 or higher.
// Add viclib as a reference in your VB.NET project
   Private Function findmark(ByVal srcimg As vicwin.imgdes, ByVal oprimg As vicwin.imgdes, ByVal resimg As vicwin.imgdes, ByVal ptarray As vicwin.COORD_VAL(), ByVal numelem As Long) As Long
        Dim rcode As Long
            '   Fill the result image with correlation coefficient data
        rcode = vicwin.correlateimages(srcimg, oprimg, resimg)
        If (rcode = vicwin.NO_ERROR) Then
            '  The pixel data in the result image will be sorted
            '  and placed in the array in descending order
            rcode = vicwin.sortpixelsbyval(resimg, ptarray(0), numelem)
        End If
        findmark = rcode
    End Function
    Private Sub mnu_findmark_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnu_findmark.Click
        Dim rcode As Long
        Dim testimage As vicwin.imgdes
        Dim markimage As vicwin.imgdes
        Dim testfile As vicwin.JpegData
        Dim markfile As vicwin.JpegData
        Dim scols, srows, ocols, orows As Long
        Dim numelem As Long
            ' For easier understanding of the sample code no error checking is performed here
            ' but recognize that you should always test the return code to verify that each function is successful 
        rcode = vicwin.jpeginfo("testc.jpg", testfile)
        rcode = vicwin.allocimage(testimage, testfile.width, testfile.length, testfile.vbitcount)
        rcode = vicwin.loadjpg("testc.jpg", testimage)
        rcode = vicwin.jpeginfo("register.jpg", markfile)
        rcode = vicwin.allocimage(markimage, markfile.width, markfile.length, markfile.vbitcount)
        rcode = vicwin.loadjpg("register.jpg", markimage)
        scols = testimage.endx - testimage.stx + 1
        srows = testimage.endy - testimage.sty + 1
        ocols = markimage.endx - markimage.stx + 1
        orows = markimage.endy - markimage.sty + 1
            ' Allocate an array to hold the pixel data for the sorting
        numelem = scols * srows
        Dim ptarray(numelem) As vicwin.COORD_VAL
        rcode = findmark(testimage, markimage, testimage, ptarray, numelem)
        If (rcode = vicwin.NO_ERROR) Then
            MsgBox("Most probable location for mark: " & ptarray(0).val & "  (" & ptarray(0).x & "," & ptarray(0).y & ")")
        End If
        rcode = vicwin.savejpg("testr.jpg", testimage, 50)
        vicwin.freeimage(markimage)
        vicwin.freeimage(testimage)
    End Sub



Find a Mark - the C# Source Code

Requires Victor Image Processing Library for 32-bit Windows v 6.0 or higher.
                case "findmark":   // Assumes three existing images:
             // the subject image is in simage, the register mark is in oimage, and the result will be placed in rimage.
                    {   // Fill the result image with correlation coefficient data
                        rcode = vicwin.correlateimages(ref simage, ref oimage, ref rimage);
                        if (rcode == vicwin.NO_ERROR)
                        {
                            int numelem;
                            string message;
                            double coef;
                            int rwidth = 0;
                            int rlength = 0;
                            rwidth = rimage.endx - rimage.stx + 1;
                            rlength = rimage.endy - rimage.sty + 1;
                            numelem = rwidth * rlength;
                            
            // Allocate an array to hold the pixel data for the sorting
                            vicwin.COORD_VAL[] ptarray = new vicwin.COORD_VAL[numelem];
                            
            // The pixel data in the result image will be sorted
            // and placed in the array in descending order
                            rcode = vicwin.sortpixelsbyval(ref rimage, ref ptarray[0], numelem);
                            if (rcode == vicwin.NO_ERROR)
                            {
                                coef = (double)ptarray[0].val / 255.0;
                                if (coef > 1.0)
                                    coef = (double)ptarray[0].val / 65535.0;
                                message = "Highest correlation value: " + coef.ToString("0.0000");
                                message = message + "       Most probable location for mark: " + "  (" + ptarray[0].x + "," + ptarray[0].y + ")";
                                MsgBox(0, message, "Find mark", 0);
                            }
                        }
                        break;
                    }


Find a Mark - the Visual Basic Source Code

Requires Victor Image Processing Library for 32-bit Windows v 5.4 or higher and the helper dll vicstats.dll.
' Add the data type definition and function declarations to vicdef32.bas ...............................................
Type COORD_VAL
   val As Long
   x As Long
   y As Long
End Type
Public Declare Function correlationcoef Lib "vicstats.dll" (ByRef srcimg As imgdes, ByRef oprimg As imgdes, ByRef pCoef As Double) As Long
Public Declare Function correlateimages Lib "vicstats.dll" (ByRef srcimg As imgdes, ByRef oprimg As imgdes, ByRef resimg As imgdes) As Long
Public Declare Function calcavglevelfloat Lib "vicstats.dll" (ByRef srcimg As imgdes, ByRef redavg As Double, ByRef grnavg As Double, ByRef bluavg As Double) As Long
Public Declare Function sortpixelsbyval Lib "vicstats.dll" (ByRef srcimg As imgdes, ByRef first_elem As COORD_VAL, ByVal nelem As Long) As Long
' The Functions .................................................... 
Private Function findmark(srcimg As imgdes, oprimg As imgdes, resimg As imgdes, ptarray As COORD_VAL, numelem As Long) As Long
Dim rcode As Long
'   Fill the result image with correlation coefficient data
    rcode = correlateimages(srcimg, oprimg, resimg)
                                                      
   If (rcode = NO_ERROR) Then
            '  The pixel data in the result image will be sorted
            '  and placed in the array in descending order
       rcode = sortpixelsbyval(resimg, ptarray, numelem)
   End If
    
   findmark = rcode
End Function
Private Sub mnufindmark_Click()
Dim rcode As Long
Dim testimage As imgdes
Dim markimage As imgdes
Dim testfile As JpegData
Dim markfile As JpegData
Dim scols, srows, ocols, orows As Long
Dim ptarray() As COORD_VAL
Dim numelem As Long
            ' For easier understanding of the sample code no error checking is performed here
   ' but recognize that you should always test the return code to verify that each function is successful 
   rcode = jpeginfo("testc.jpg", testfile)
   rcode = allocimage(testimage, testfile.width, testfile.length, testfile.vbitcount)
   rcode = loadjpg("testc.jpg", testimage)
   rcode = jpeginfo("register.jpg", markfile)
   rcode = allocimage(markimage, markfile.width, markfile.length, markfile.vbitcount)
   rcode = loadjpg("register.jpg", markimage)
   scols = testimage.endx - testimage.stx + 1
   srows = testimage.endy - testimage.sty + 1
   ocols = markimage.endx - markimage.stx + 1
   orows = markimage.endy - markimage.sty + 1
   numelem = scols * srows
            ' Allocate an array to hold the pixel data for the sorting
   ReDim ptarray(0 To numelem - 1) As COORD_VAL
   
   rcode = findmark(testimage, markimage, testimage, ptarray(0), numelem)
   If (rcode = NO_ERROR) Then
      MsgBox ("Most probable location for mark: " & ptarray(0).val & "  (" & ptarray(0).x & "," & ptarray(0).y & ")")
   End If
   rcode = savejpg("testr.jpg", testimage, 50)
   freeimage markimage
   freeimage testimage
End Sub


Find a Mark - the C Source Code

Requires Victor Image Processing Library for 32-bit Windows v 5.4 or higher and the helper dll vicstats.dll.
// Add these declarations to vicdefs.h
typedef struct { unsigned val, x, y; } COORD_VAL;
int WINAPI correlationcoef(imgdes *srcimg, imgdes *oprimg, double *pCoef);
int WINAPI correlateimages(imgdes *srcimg, imgdes *oprimg, imgdes *resimg);
int WINAPI calcavglevelfloat(imgdes *srcimg, double *redavg, double *grnavg, double *bluavg);
int WINAPI sortpixelsbyval(imgdes *srcimg, COORD_VAL *darray, int nelem);
int findmark(imgdes *srcimg, imgdes *oprimg, imgdes *resimg, COORD_VAL *ptarray, int numelem)  
{
   int rcode;
            // Fills the result image with correlation coefficient data
   rcode = correlateimages(srcimg, oprimg, resimg); 
                                                      
   if(rcode == NO_ERROR) {
            // The pixel data in the result image will be sorted
            // and placed in the array in descending order
      rcode = sortpixelsbyval(resimg, ptarray, numelem);
      }
   return (rcode);
}
void DoMenuFindmark(HWND hWnd)
{
   int rcode;
   imgdes testimage;
   imgdes markimage;
   JpegData testfile;
   JpegData markfile;
   int scols, srows, ocols, orows;
   COORD_VAL *ptarray;
   int numelem;
            // For easier understanding of the sample code no error checking is performed here
   // but recognize that you should always test the return code to verify that each function is successful 
   rcode = jpeginfo("testc.jpg", &testfile);
   rcode = allocimage(&testimage, testfile.width, testfile.length, testfile.vbitcount);
   rcode = loadjpg("testc.jpg", &testimage);
   rcode = jpeginfo("register.jpg", &markfile);
   rcode = allocimage(&markimage, markfile.width, markfile.length, markfile.vbitcount);
   rcode = loadjpg("register.jpg", &markimage);
   scols = CALC_WIDTH(&testimage);
   srows = CALC_HEIGHT(&testimage);
   ocols = CALC_WIDTH(&markimage);
   orows = CALC_HEIGHT(&markimage);
   numelem =  scols * srows;
            // Allocate an array to hold the pixel data for the sorting
   ptarray = calloc(numelem, sizeof(COORD_VAL));
   rcode = findmark(&testimage, &markimage, &testimage, ptarray, numelem);
   if(rcode == NO_ERROR) {
      char szBuff[128];
            // Display the values for the four most likely locations
      wsprintf(szBuff, "Most probable locations for mark:"
         "\n%3d: (%3d, %3d)"
         "\n%3d: (%3d, %3d)"
         "\n%3d: (%3d, %3d)"
         "\n%3d: (%3d, %3d)",
          ptarray[0].val, ptarray[0].x, ptarray[0].y, 
          ptarray[1].val, ptarray[1].x, ptarray[1].y,
          ptarray[2].val, ptarray[2].x, ptarray[2].y,
          ptarray[3].val, ptarray[3].x, ptarray[3].y
          );
      MessageBox(hWnd, szBuff, szAppName, MB_OK);
      }
   if(ptarray)
      free(ptarray);
   savejpg("testr.jpg", &testimage, 50);
   freeimage(&markimage);
   freeimage(&testimage);
}
Victor Image Processing Library

Victor Image Processing Library homepage | Victor Product Summary | more source code




Copyright © 2003 Catenary Systems Inc. All rights reserved. Victor Image Processing Library is a trademark of Catenary Systems.