1. 程式人生 > >基於MFC開發的指紋識別系統.

基於MFC開發的指紋識別系統.

MFC-FingerPrint

基於MFC開發的指紋識別系統.


效果圖如下:

1

在第12步特徵入庫中,會對當前指紋的mdl資料與databases中所有的mdl進行對比,然後返回識別結果.

一.載入影象

在點選之後,選擇需要識別的圖片. 圖片路徑為beginfilename.

void CFingerDlg::OnBnClickedOk1()
{
    CFileDialog    dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("Describe Files (*.bmp)|*.bmp|All Files (*.*)|*.*||"), NULL);

    if (dlgFile.DoModal())
    {
        strFile = dlgFile.GetPathName();
    }
    char *info = "";

    USES_CONVERSION;
    char * beginfilename = T2A(strFile);
    Step1_LoadBmpImage(beginfilename,info);

    ShowImageInCtrl(m_picCtrl1, beginfilename);

    // TODO: 在此新增控制元件通知處理程式程式碼
}

Step1_LoadBmpImage中就是獲取初始圖片的RGB資訊.

int Step1_LoadBmpImage(char *beginfilename,char* info) {
    char *filename = beginfilename;
    CopyFile(ToWideChar(filename), ToWideChar(STEP_TXT_1), false);

    int iWidth, iHeight, iDepth;
    int flag = ReadBMPImgFilePara(filename, iWidth, iHeight, iDepth);
    if (flag != 0) {
        //sprintf(info,"影象載入失敗");
        ::MessageBox(NULL, _T("影象載入失敗"), _T("error"), MB_OK);
        return -1;
    }
    unsigned char *data = new unsigned char[iWidth*iHeight];
    flag = ReadBMPImgFileData(filename, data);
    if (flag != 0) {
        //sprintf(info, "影象資料讀取失敗");
        ::MessageBox(NULL, _T("影象資料讀取失敗"), _T("error"), MB_OK);
        delete[] data;
        return -2;
    }
    flag = SaveDataToTextFile(STEP_TXT_1, data, iWidth, iHeight);
    if (flag != 0) {
        //sprintf(info,"資料儲存失敗");
        ::MessageBox(NULL, _T("資料儲存失敗"), _T("error"), MB_OK);
        delete[] data;
        return -3;
    }
    //sprintf(info, "源圖[%s],寬度[%d],高度[%d],深度[%d b]",filename,iWidth,iHeight,iDepth);
    delete[] data;
    return 0;
}

其中具體的Txt與BMP轉換參考具體原始碼.


二.中值濾波

中值濾波實現演算法,ucImg由第一步得來.

int MidFilter(unsigned char *ucImg, unsigned char *ucDstImg, int iWidth, int iHeight) {
    memset(ucDstImg, 0, iWidth*iHeight);
    unsigned char *pUp, *pDown, *pImg;
    unsigned char x[9];
    for (int i = 1; i < iHeight - 1; i++) {
        pUp = ucImg + (i - 1)*iWidth;
        pImg = ucImg + i * iWidth;
        pDown = ucImg + (i + 1)*iWidth;
        int j;
        for (j = 1; j < iWidth - 1; j++) {
            pUp++;
            pImg++;
            pDown++;
            x[0] = *(pUp - 1);
            x[1] = *(pImg - 1);
            x[2] = *(pDown - 1);
            x[3] = *pUp;
            x[4] = *pImg;
            x[5] = *pDown;
            x[6] = *(pUp + 1);
            x[7] = *(pImg + 1);
            x[8] = *(pDown + 1);

            Sort(x, 9);
            *(ucDstImg + i * iWidth + j) = x[4];
        }
    }
    int j;
    pDown = ucImg + iWidth;
    for (j = 1; j < iWidth - 1; j++) {
        x[0] = *(ucImg + j - 1);
        x[1] = *(ucImg + j);
        x[2] = *(ucImg + j + 1);
        x[3] = *(pDown + j - 1);
        x[4] = *(pDown + j);
        x[5] = *(pDown + j + 1);
        Sort(x, 6);
        *(ucDstImg + j) = x[3];
    }
    pUp = ucImg + iWidth * (iHeight - 2);
    pDown = ucImg + iWidth * (iHeight - 1);
    for (j = 1; j < iWidth - 1; j++) {
        x[0] = *(pDown + j - 1);
        x[1] = *(pDown + j);
        x[2] = *(pDown + j + 1);
        x[3] = *(pUp + j - 1);
        x[4] = *(pUp + j);
        x[5] = *(pUp + j + 1);
        Sort(x, 6);
        *(ucDstImg + iWidth * (iHeight - 1) + j) = x[3];
    }
    x[0] = *(ucImg);
    x[1] = *(ucImg + 1);
    x[2] = *(ucImg + iWidth);
    x[3] = *(ucImg + iWidth + 1);
    Sort(x, 4);
    *(ucDstImg) = x[2];

    x[0] = *(ucImg + iWidth - 1);
    x[1] = *(ucImg + iWidth - 2);
    x[2] = *(ucImg + 2 * iWidth - 1);
    x[3] = *(ucImg + 2 * iWidth - 2);

    Sort(x, 4);
    *(ucDstImg + iWidth - 1) = x[2];

    x[0] = *(ucImg + iWidth * (iHeight - 1));
    x[1] = *(ucImg + iWidth * (iHeight - 2));
    x[2] = *(ucImg + iWidth * (iHeight - 1) + 1);
    x[3] = *(ucImg + iWidth * (iHeight - 2) + 1);
    Sort(x, 4);
    *(ucDstImg + (iHeight - 1)*iWidth) = x[2];
    x[0] = *(ucImg + iWidth * (iHeight - 0) - 1);
    x[1] = *(ucImg + iWidth * (iHeight - 1) - 1);
    x[2] = *(ucImg + iWidth * (iHeight - 0) - 2);
    x[3] = *(ucImg + iWidth * (iHeight - 1) - 2);
    Sort(x, 4);

    *(ucDstImg + (iHeight - 0)*iWidth - 1) = x[2];

    return 0;
}

2


三.均值化

int HistoNormalize(unsigned char* ucImg,unsigned char* ucNormImg, int iWidth,int iHeight) {
    unsigned int Histogram[256];

    memset(Histogram, 0, 256 * sizeof(int));
    for (int i = 0; i < iHeight; i++) {
        for (int j = 0; j < iWidth; j++) {
            Histogram[ucImg[i*iWidth + j]]++;
        }
    }
    double dMean = 0;
    for (int i = 1; i < 255; i++) {
        dMean += i * Histogram[i];
    }
    dMean = int(dMean/(iWidth*iHeight));
    double dSigma = 0;
    for (int i = 0; i < 255; i++) {
        dSigma += Histogram[i] * (i - dMean)*(i-dMean);
    }
    dSigma /= (iWidth*iHeight);
    dSigma = sqrt(dSigma);

    double dMean0 = 128, dSigma0 = 128;
    double dCoeff = dSigma0 / dSigma;
    for (int i = 0; i < iHeight; i++) {
        for(int j=0;j<iWidth;j++){
            double dVal = ucImg[i*iWidth + j];
            dVal = dMean0 + dCoeff * (dVal-dMean0);
            if (dVal < 0) {
                dVal = 0;
            }
            else if (dVal > 255) {
                dVal = 255;
            }
            ucNormImg[i*iWidth + j] = (unsigned char)dVal;
        }
    }
    return 0;
}

3


四.方向計算

int ImgDirection(unsigned char* ucImg,float* fDirc,int iWidth,int iHeight) {
    const int SEMISIZ = 7;
    int dx[SEMISIZ * 2 + 1][SEMISIZ * 2 + 1];
    int dy[SEMISIZ * 2 + 1][SEMISIZ * 2 + 1];
    float fx, fy;
    memset(fDirc, 0, iWidth*iHeight * sizeof(float));
    for (int y = SEMISIZ + 1; y < iHeight - SEMISIZ - 1; y++) {
        for (int x = SEMISIZ + 1; x < iWidth - SEMISIZ - 1; x++) {
            for (int j = 0; j < SEMISIZ * 2 + 1; j++) {
                for (int i = 0; i < SEMISIZ * 2 + 1; i++) {
                    int index1 = (y + j - SEMISIZ)*iWidth + x + i - SEMISIZ;
                    int index2 = (y + j - SEMISIZ)*iWidth + x + i - SEMISIZ - 1;
                    int index3 = (y + j - SEMISIZ - 1)*iWidth + x + i - SEMISIZ;
                    dx[i][j] = int(ucImg[index1] - ucImg[index2]);
                    dy[i][j] = int(ucImg[index1] - ucImg[index3]);
                }
            }
            fx = 0.0;
            fy = 0.0;
            for (int j = 0; j < SEMISIZ * 2 + 1; j++) {
                for (int i = 0; i < SEMISIZ * 2 + 1; i++) {
                    fx += 2 * dx[i][j] * dy[i][j];
                    fy += (dx[i][j] * dx[i][j] - dy[i][j] * dy[i][j]);
                }
            }
            fDirc[y*iWidth + x] = atan2(fx,fy);
        }
    }
    return 0;
}

4


五.頻率計算

int DircLowPass(float *fDirc,float* fFitDirc,int iWidth,int iHeight) {
    const int DIR_FILTER_SIZE = 2;
    int blocksize = 2 * DIR_FILTER_SIZE + 1;
    int imgsize = iWidth * iHeight;
    float *filter = new float[blocksize*blocksize];
    float *phix = new float[imgsize];
    float *phiy = new float[imgsize];
    float *phi2x = new float[imgsize];
    float *phi2y = new float[imgsize];
    memset(fFitDirc,0,sizeof(float)*iWidth*iHeight);
    float tempSum = 0.0;
    for (int y = 0; y < blocksize; y++) {
        for (int x = 0; x < blocksize; x++) {
            filter[y*blocksize + x] = (float)(blocksize - (abs(DIR_FILTER_SIZE - x) + abs(DIR_FILTER_SIZE - y)));
            tempSum += filter[y*blocksize + x];
        }
    }
    for (int y = 0; y < blocksize; y++) {
        for (int x = 0; x < blocksize; x++) {
            filter[y*blocksize + x] /= tempSum;
        }
    }
    for(int y=0;y<iHeight;y++){
        for (int x = 0; x < iWidth; x++) {
            phix[y*iWidth + x] = cos(fDirc[y*iWidth + x]);
            phiy[y*iWidth + x] = sin(fDirc[y*iWidth + x]);
        }
    }
    memset(phi2x, 0, sizeof(float)*imgsize);
    memset(phi2y, 0, sizeof(float)*imgsize);
    float nx, ny;
    int val;
    for (int y = 0; y < iHeight - blocksize; y++) {
        for (int x = 0; x < iWidth - blocksize; x++) {
            nx = 0.0;
            ny = 0.0;
            for (int j = 0; j < blocksize; j++) {
                for (int i = 0; i < blocksize; i++) {
                    val = (x + i) + (j + y)*iWidth;
                    nx += filter[j*blocksize + i] * phix[val];
                    ny += filter[j*blocksize + i] * phiy[val];
                }
            }
            val = x + y * iWidth;
            phi2x[val] = nx;
            phi2y[val] = ny;
        }
    }

    for (int y = 0; y < iHeight - blocksize; y++) {
        for (int x = 0; x < iWidth - blocksize; x++) {
            val = x + y * iWidth;
            fFitDirc[val] = atan2(phi2y[val],phi2x[val])*0.5;
        }
    }
    delete[] phi2y;
    delete[] phi2x;
    delete[] phiy;
    delete[] phix;

    return 0;
}

5


六.掩碼計算

int GetMask(unsigned char* ucImg,float *fDirection,float *fFrequency,unsigned char *ucMask,int iWidth,int iHeight) {
    float freqMin = 1.0 / 25.0;
    float freqMax = 1.0 / 3.0;
    int x, y, k;
    int pos, posout;
    memset(ucMask,0,iWidth*iHeight);
    for (y = 0; y < iHeight; y++) {
        for (x = 0; x < iWidth; x++) {
            pos = x + y * iWidth;
            posout = x + y * iWidth;
            ucMask[posout] = 0;
            if (fFrequency[pos] >= freqMin && fFrequency[pos] <= freqMax) {
                ucMask[posout] = 255;
            }
        }
    }
    for (k = 0; k < 4; k++) {
        for (y = 1; y < iHeight - 1; y++) {
            for (x = 1; x < iWidth - 1; x++) {
                if (ucMask[x + y * iWidth] == 0xFF) {
                    ucMask[x - 1 + y * iWidth] |= 0x80;
                    ucMask[x + 1 + y * iWidth] |= 0x80;
                    ucMask[x + (y-1) * iWidth] |= 0x80;
                    ucMask[x + (y+1) * iWidth] |= 0x80;
                }
            }
        }
        for (y = 1; y < iHeight - 1; y++) {
            for (x = 1; x < iWidth - 1; x++) {
                if (ucMask[x + y * iWidth]) {
                    ucMask[x + y * iWidth] = 0xFF;
                }
            }
        }
    }
    for (k = 0; k < 12; k++) {
        for (y = 1; y < iHeight - 1; y++) {
            for (x = 1; x < iWidth - 1; x++) {
                if (ucMask[x + y * iWidth] == 0x0) {
                    ucMask[x - 1 + y * iWidth] &= 0x80;
                    ucMask[x + 1 + y * iWidth] &= 0x80;
                    ucMask[x + (y - 1) * iWidth] &= 0x80;
                    ucMask[x + (y + 1) * iWidth] &= 0x80;
                }
            }
        }
        for (y = 1; y < iHeight - 1; y++) {
            for (x = 1; x < iWidth - 1; x++) {
                if (ucMask[x + y * iWidth] != 0xFF) {
                    ucMask[x + y * iWidth] = 0x0;
                }
            }
        }
    }
    return 0;
}

6


七.Gabor增強

int GaborEnhance(unsigned char* ucImg, float* fDirection, float* fFrequency, unsigned char* ucMask, unsigned char* ucImgEnhanced, int iWidth, int iHeight) {
    const float PI = 3.141592654;
    int i, j, u, v;
    int wg2 = 5;
    float sum, f, g;
    float x2, y2;
    float dx2 = 1.0 / (4.0*4.0);
    float dy2 = 1.0 / (4.0*4.0);
    memset(ucImgEnhanced,0,iWidth*iHeight);
    for (j = wg2; j < iHeight - wg2; j++) {
        for (i = wg2; i < iWidth - wg2; i++) {
            if (ucMask[i + j * iWidth] == 0) {
                continue;
            }
            g = fDirection[i+j*iWidth];
            f = fFrequency[i+j*iWidth];
            g += PI / 2;
            sum = 0.0;
            for (v = -wg2; v <= wg2; v++) {
                for (u = -wg2; u <= wg2; u++) {
                    x2 = -u * sin(g) + v * cos(g);
                    y2 = u * cos(g) + v * sin(g);
                    sum += exp(-0.5*(x2*x2*dx2 + y2 * y2*dy2))*cos(2 * PI*x2*f)*ucImg[(i - u) + (j - v)*iWidth];
                }
            }
            if (sum > 255.0) {
                sum = 255.0;
            }
            if (sum < 0.0) {
                sum = 0.0;
            }
            ucImgEnhanced[i + j * iWidth] = (unsigned char)sum;
        }
    }
    return 0;
}

7


八.二值化


int BinaryImg(unsigned char* ucImage,unsigned char* ucBinImage,int iWidth,int iHeight,unsigned char uThreshold) {
    unsigned char *pStart = ucImage, *pEnd = ucImage + iWidth * iHeight;
    unsigned char *pDest = ucBinImage;
    while (pStart < pEnd) {
        *pDest = *pStart > uThreshold ? 1 : 0;
        pStart++;
        pDest++;
    }
    return 0;
}

int BinaryToGray(unsigned char *ucBinImg,unsigned char *ucGrayImg,int iWidth,int iHeight) {
    unsigned char *pStart = ucBinImg, *pEnd = ucBinImg + iWidth * iHeight;
    unsigned char *pDest = ucGrayImg;

    while (pStart<pEnd) {
        *pDest = (*pStart) > 0 ? 255 : 0;
        pStart++;
        pDest++;
    }
    return 0;
}

8


九.細化

int Thinning(unsigned char *ucBinedImg,unsigned char *ucThinnedImage,int iWidth,int iHeight,int iIterativeLimit) {
    unsigned char x1, x2, x3, x4, x5, x6, x7, x8, xp;
    unsigned char g1, g2, g3, g4;
    unsigned char b1, b2, b3, b4;
    unsigned char np1, np2, npm;
    unsigned char *pUp, *pDown, *pImg;
    int iDeletePoints = 0;

    memcpy(ucThinnedImage,ucBinedImg,iWidth*iHeight);
    for (int it = 0; it < iIterativeLimit; it++) {
        iDeletePoints = 0;
        for (int i = 1; i < iHeight - 1; i++) {
            pUp = ucBinedImg + (i - 1)*iWidth;
            pImg = ucBinedImg + i * iWidth;
            pDown = ucBinedImg + (i + 1)*iWidth;
            for (int j = 1; j < iWidth - 1; j++) {
                pUp++;
                pImg++;
                pDown++;
                if (!*pImg) {
                    continue;
                }
                x6 = *(pUp - 1);
                x5 = *(pImg - 1);
                x4 = *(pDown - 1);
                x7 = *pUp;
                xp = *pImg;
                x3 = *pDown;
                x8 = *(pUp + 1);
                x1 = *(pImg+1);
                x2 = *(pDown+1);


                b1 = !x1 && (x2 == 1 || x3 == 1);
                b2 = !x3 && (x4 == 1 || x5 == 1);
                b3 = !x5 && (x6 == 1 || x7 == 1);
                b4 = !x7 && (x8 == 1 || x1 == 1);

                g1 = (b1 + b2 + b3 + b4) == 1;

                np1 = x1 || x2;
                np1 += x3 || x4;
                np1 += x5 || x6;
                np1 += x7 || x8;
                np2  = x2 || x3;
                np2 += x4 || x5;
                np2 += x6 || x7;
                np2 += x8 || x1;

                npm = np1 > np2 ? np2 : np1;
                g2 = npm >= 2 && npm <= 3;
                g3 = (x1 && (x2 || x3 || !x8)) == 0;
                g4 = (x5 && (x6 || x7 || !x4)) == 0;

                if (g1&&g2&&g3) {
                    ucThinnedImage[iWidth*i + j] = 0;
                    ++iDeletePoints;
                }
            }
        }
        memcpy(ucBinedImg,ucThinnedImage,iWidth*iHeight);
        for (int i = 1; i < iHeight - 1;i++) {
            pUp = ucBinedImg + (i - 1)*iWidth;
            pImg = ucBinedImg + i * iWidth;
            pDown = ucBinedImg + (i+1) * iWidth;
            for (int j = 1; j < iWidth - 1; j++) {
                pUp++;
                pImg++;
                pDown++;
                if (!*pImg) {
                    continue;
                }
                x6 = *(pUp - 1);
                x5 = *(pImg - 1);
                x4 = *(pDown - 1);

                x7 = *pUp;
                xp = *pImg;
                x3 = *pDown;

                x8 = *(pUp + 1);
                x1 = *(pImg + 1);
                x2 = *(pDown + 1);

                b1 = !x1 && (x2 == 1 || x3 == 1);
                b2 = !x3 && (x4 == 1 || x5 == 1);
                b3 = !x5 && (x6 == 1 || x7 == 1);
                b4 = !x7 && (x8 == 1 || x1 == 1);

                g1 = (b1 + b2 + b3 + b4) == 1;

                np1 = x1 || x2;
                np1 += x3 || x4;
                np1 += x5 || x6;
                np1 += x7 || x8;

                np2 = x2 || x3;
                np2 += x4 || x5;
                np2 += x6 || x7;
                np2 += x8 || x1;

                npm = np1 > np2 ? np2 : np1;
                g2 = npm >= 2 && npm <= 3;

                g3 = (x1 && (x2 || x3 || !x8)) == 0;
                g4 = (x5 && (x6 || x7 || !x4)) == 0;

                if (g1&&g2&&g4) {
                    ucThinnedImage[iWidth*i+j] = 0;
                    ++iDeletePoints;
                }
            }
        }

        memcpy(ucBinedImg,ucThinnedImage,iWidth*iHeight);

        if (iDeletePoints == 0) {
            break;
        }
    }

    for (int i = 0; i < iHeight; i++) {
        for (int j = 0; j < iWidth; j++) {
            if (i < 16) {
                ucThinnedImage[i*iWidth + j] = 0;
            }
            else if (i >= iHeight - 16) {
                ucThinnedImage[i*iWidth + j] = 0;
            }
            else if (j < 16) {
                ucThinnedImage[i*iWidth + j] = 0;
            }
            else if (j >= iWidth - 16) {
                ucThinnedImage[i*iWidth + j] = 0;
            }
        }
    }
    return 0;
}

9


十.特徵提取

int CutEdge(MINUTIAE* minutiaes,int count,unsigned char*ucImg,int iWidth,int iHeight) {
    int minuCount = count;
    int x, y, type;
    bool del;
    int *pFlag = new int[minuCount];
    memset(pFlag,0,sizeof(int)*minuCount);
    for (int i = 0; i < minuCount; i++) {
        y = minutiaes[i].y - 1;
        x = minutiaes[i].x - 1;
        type = minutiaes[i].type ;
        del = true;
        if (x < iWidth / 2) {
            if (abs(iWidth / 2 - x) > abs(iHeight / 2 - y)) {
                while (--x >= 0) {
                    if (ucImg[x + y * iWidth] > 0) {
                        del = false;
                        break;
                    }
                }
            }
            else {
                if (y > iHeight / 2) {
                    while (++y < iHeight) {
                        if (ucImg[x + y * iWidth] > 0) {
                            del = false;
                            break;
                        }
                    }
                }
                else {
                    while (--y == 0) {
                        if (ucImg[x + y * iWidth] > 0) {
                            del = false;
                            break;
                        }
                    }
                }
            }
        }
        else {
            if (abs(iWidth / 2 - x) > abs(iHeight / 2 - y)) {
                while (++x < iWidth) {
                    if (ucImg[x + y * iWidth] > 0) {
                        del = false;
                        break;
                    }
                }
            }
            else {
                if (y > iHeight / 2) {
                    while (++y < iHeight) {
                        if (ucImg[x + y * iWidth] > 0) {
                            del = false;
                            break;
                        }
                    }
                }
                else {
                    while (--y >= 0) {
                        if (ucImg[x + y * iWidth] > 0) {
                            del = false;
                            break;
                        }
                    }
                }
            }
        }
        if (del) {
            pFlag[i] = 1;
            continue;
        }
    }
    int newCount = 0;
    for (int i = 0; i < minuCount; i++) {
        if (pFlag[i] == 0) {
            memcpy(&minutiaes[newCount],&minutiaes[i],sizeof(MINUTIAE));
            newCount++;
        }
    }
    delete[] pFlag;
    pFlag = NULL;
    return newCount;
}

10


十一.特徵過濾

int MinuFilter(unsigned char *minuData,unsigned char *thinData,MINUTIAE *minutiaes,int &minuCount,int iWidth,int iHeight) {
    float *dir = new float[iWidth*iHeight];
    memset(dir,0,iWidth*iHeight*sizeof(float));
    ImgDirection(thinData,dir,iWidth,iHeight);
    unsigned char* pImg;
    unsigned char val;
    int temp = 0;
    for (int i = 1; i < iHeight - 1; i++) {
        pImg = minuData + i * iWidth;
        for (int j = 1; j < iWidth - 1; j++) {
            ++pImg;
            val = *pImg;
            if(val>0){
                minutiaes[temp].x = j + 1;
                minutiaes[temp].y = i + 1;
                minutiaes[temp].theta = dir[i*iWidth+j];
                minutiaes[temp].type = int(val);
                ++temp;
            }
        }
    }
    delete[] dir;
    minuCount = CutEdge(minutiaes,minuCount,thinData,iWidth,iHeight);
    int *pFlag = new int[minuCount];
    memset(pFlag,0,sizeof(int)*minuCount);
    int x1, x2, y1, y2, type1, type2;
    for (int i = 0; i < minuCount; i++) {
        x1 = minutiaes[i].x;
        y1 = minutiaes[i].y;
        type1 = minutiaes[i].type;
        for (int j = i + 1; j < minuCount; j++) {
            if (pFlag[i] == 1) {
                continue;
            }
            x2 = minutiaes[j].x;
            y2 = minutiaes[j].y;
            type2 = minutiaes[j].type;

            int r = (int)sqrt(float((y1-y2)*(y1-y2)+(x1-x2)*(x1-x2)));

            if (r <= 4) {
                if (type1 == type2) {
                    if (type1 == 1) {
                        pFlag[i] = pFlag[j] = 1;
                    }
                    else {
                        pFlag[j] = 1;
                    }
                }
                else if (type1 == 1) {
                    pFlag[i] = 1;
                }
                else {
                    pFlag[j] = 1;
                }
            }
        }

    }
    int newCount = 0;
    for (int i = 0; i < minuCount; i++) {
        if (pFlag[i] == 0) {
            memcpy(&minutiaes[newCount],&minutiaes[i],sizeof(MINUTIAE));
            newCount++;
        }
    }
    delete[] pFlag;
    minuCount = newCount;
    return 0;
}

11