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:
- determine the dimensions and pixel depth of the test and reference images
- allocate buffer space for the images
- load the images
- fill the result image with correlation coefficient data calculated between the test image and the reference image
- sort the correlation coefficient data to determine the most probable location of the mark
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).
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 SubFind 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); }
No comments:
Post a Comment