官术网_书友最值得收藏!

5.4.1 人臉膚色相似度比較

編程實現

[1] 添加繼承自ImageDib類的FaceDetect類進行有關人臉檢測的算法編程與實現。在文件FaceDetect.h中定義該類如代碼5-1所示。

代碼5-1 FaceDetect類

        class FaceDetect : public ImageDib
        {
            public:
                int m_nBitCountOut;                   //輸出圖像每像素位數
                unsigned char * m_pImgDataOut;       //輸出圖像位圖數據指針
                LPRGBQUAD m_lpColorTableOut;     //輸出圖像顏色表
                unsigned char * m_pImgDataIn;    //輸入圖像位圖數據指針
                double** m_pSimArray;            //相似度矩陣
                double Cb_Mean;
                double Cr_Mean;
                double Cov00;
                double Cov01;
                double Cov10;
                double Cov11;
        private:
                int m_imgWidthOut;                //輸出圖像的寬,像素為單位
                int m_imgHeightOut;               //輸出圖像的高,像素為單位
                int m_nColorTableLengthOut;      //輸出圖像顏色表長度
        public:
                void CalSBound(int top,int bottom,int left,int right);
                FaceDetect();                     //不帶參數的構造函數
                FaceDetect(CSize size, int nBitCount, LPRGBQUAD lpColorTable,
                    unsigned char *pImgData1,unsigned char *pImgData2);
                                                  //帶參數的構造函數
                ~FaceDetect();                    //析構函數
                bool CalBin();
                void CalMedFl(double **s,int w,int h,int n);
                void CalSim();
                CSize GetDimensions();           //以像素為單位返回輸出圖像的寬和高
        };

[2] 在視圖類里添加消息映射函數Onsimilardegree(),以進行相似度計算。Onsimilardegree ()函數代碼如代碼5-2所示。

代碼5-2 Onsimilardegree()函數

        void CDemo1View::Onsimilardegree()
        {
                //獲取文檔類指針
            CDemo1Doc *pDoc=GetDocument();
            //獲取ImgCenterDib類對象m_dib的指針,訪問當前DIB數據
            ImageDib *pDib=pDoc->GetPDib();
            //只處理彩色圖像
            if(pDib->m_nBitCount!=24){
                ::MessageBox(0, "只處理彩色圖像", MB_OK,0);
                return ;
            }
            FaceDetect simcalculation(pDib->GetDimensions(),pDib->m_nBitCount,
                pDib->m_lpColorTable, pDib->m_pImgData,NULL);
            simcalculation.CalSim();
            //建立一個新視圖,顯示結果
            CMainFrame* pFrame = (CMainFrame *)(AfxGetApp()->m_pMainWnd);
            //發送新建文件的消息,創建一個新的文檔-視圖
            pFrame->SendMessage(WM_COMMAND, ID_FILE_NEW);
            //獲取新建視圖指針
            CDemo1View* pView=(CDemo1View*)pFrame->MDIGetActive()->GetActiveView();
            //獲取相關聯的新的文檔類指針
            CDemo1Doc* pDocNew=pView->GetDocument();
            //獲取新文檔中的ImgCenterDib類對象指針
            ImageDib *dibNew=pDocNew->GetPDib();
            //將變換后的輸出圖像作為新建文檔的DIB進行顯示
            dibNew->ReplaceDib(simcalculation.GetDimensions(),simcalculation.m_nBitCou ntOut,simca lculation.m_lpColorTableOut, simcalculation.m_pImgDataOut);
            //設置滾動窗口
            pView->OnInitialUpdate();
            //文檔數據置臟,提示存盤信息
            pDocNew->SetModifiedFlag(TRUE);
            //各視圖刷新顯示
            pDocNew->UpdateAllViews(pView);
        }

[3] 上述代碼中,調用了FaceDetect類中的CalSim()函數,以進行膚色相似度計算,其具體代碼如代碼5-3所示。

代碼5-3 CalSim()函數

        void FaceDetect::CalSim()
        {
            //若為灰度圖像,則返回
            if(m_nBitCount==8) return;
            //釋放舊的輸出圖像數據及顏色表緩沖區
            if(m_pImgDataOut!=NULL){
                delete []m_pImgDataOut;
                m_pImgDataOut=NULL;
            }
            if(m_lpColorTableOut!=NULL){
                delete []m_lpColorTableOut;
                m_lpColorTableOut=NULL;
            }
            //灰值化后,每像素位數為8比特
            m_nBitCountOut=8;
            //顏色表長度
            m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut);
            //申請顏色表緩沖區,生成灰度圖像的顏色表
            if(m_nColorTableLengthOut!=0){
            m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut];
                for(int i=0; i<m_nColorTableLengthOut;i++){
                    m_lpColorTableOut[i].rgbBlue=i;
                    m_lpColorTableOut[i].rgbGreen=i;
                    m_lpColorTableOut[i].rgbRed=i;
                    m_lpColorTableOut[i].rgbReserved=0;
                }
            }
            //輸入圖像每像素字節數,彩色圖像為3字節/像素
            int pixelByteIn=3;
            //輸入圖像每行像素所占字節數,必須是4的倍數
            int lineByteIn=(m_imgWidth*pixelByteIn+3)/4*4;
            //輸出圖像的寬高,與輸入圖像相等
            m_imgWidthOut=m_imgWidth;
            m_imgHeightOut=m_imgHeight;
            //輸出圖像每行像素所占字節數,必須是4的倍數
            int lineByteOut=(m_imgWidth*m_nBitCountOut/8+3)/4*4;
            //申請輸出圖像位圖數據緩沖區
            m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeight];
            //循環變量,圖像的坐標
            int i,j,k,j1,j2,flag;
            char c_t1[4];
            for(i=0;i<m_imgHeight;i++){
                for(j=0;j<m_imgWidth;j++){
                    *(m_pImgDataOut+i*lineByteOut+j)=255;
                }
            }
            m_pSimArray = new double*[m_imgHeight];
            for(i=0;i<m_imgHeight;i++)
                m_pSimArray[i] = new double[m_imgWidth];
            //RGB色彩空間變換到YCgCr色彩空間,然后計算該點屬于皮膚區域的概率
            for(i=0;i<m_imgHeight;i++)
                for (j=0;j<m_imgWidth;j++){
                    for(k=0;k<3;k++){
                        c_t1[k]=*(m_pImgDataIn1+i*lineByteIn+j*pixelByteIn+k);
                    }
                    int C_b=(int)c_t1[0]&255;
                    int C_g=(int)c_t1[1]&255;
                    int C_r=(int)c_t1[2]&255;
                    double Cb=(128-37.797*C_r/255-74.203*C_g/255+112*C_b/255);
                    double Cr=(128+112*C_r/255-93.786*C_g/255-18.214*C_b/255);
                    double tt =(Cb-Cb_Mean)*((Cb-Cb_Mean)*Cov11-(Cr-Cr_Mean)*Cov10)+
                        (Cr-Cr_Mean)*(-(Cb-Cb_Mean)*Cov01+(Cr-Cr_Mean)*Cov00);
                    tt =(-0.5*tt)/(Cov00*Cov11-Cov01*Cov10);
                    m_pSimArray[i][j]=exp(tt);
                }
                //調用中值濾波函數
                CalMedFl(m_pSimArray,m_imgWidth, m_imgHeight,9);
                //統計出該幅圖像上所有像素點的最大膚色相似度
                double max=0.0;
                for(i=0;i<m_imgHeight;i++)
                    for (j=0;j<m_imgWidth;j++){
                        if(m_pSimArray[i][j]>max)
                            max=m_pSimArray[i][j];
                    }
                //將各個像素的膚色相似度值歸一化
                for( i=0;i<m_imgHeight;i++)
                    for (j=0;j<m_imgWidth;j++){
                        m_pSimArray[i][j]= m_pSimArray[i][j]/max;
                    }
                //將各像素的膚色相似度值變換到[0,255]上,以進行灰度圖像的顯示
                for(i=0;i<m_imgHeight;i++)
                    for(j=0;j<m_imgWidth;j++){
                        *(m_pImgDataOut+i*lineByteOut+j)=(int)(m_pSimArray[i][j]*255);
                    }
}

[4] CalSim()函數調用了FaceDetect類中的CalMedFl()函數,以進行中值濾波,其具體代碼如代碼5-4所示。

代碼5-4 CalMedFl()函數

        void FaceDetect::CalMedFl(double **s, int w, int h, int n)
        {
            int i,j;
            double **temp;
            temp = new double*[h+2*(int)(n/2)];
            for(i=0;i<h+2*(int)(n/2);i++)    temp[i] = new double[w+2*(int)(n/2)];
            for(i=0;i<w+2*(int)(n/2);i++)
                for(j=0;j<h+2*(int)(n/2);j++)    temp[j][i] = 0.0;
            for(i=0;i<h;i++)
                for(j=0;j<w;j++)
                    temp[i+(int)(n/2)][j+(int)(n/2)]=s[i][j];
            for(i=0;i<h;i++)
                for(j=0;j<w;j++) {
                    s[i][j]=0.0;
                    for(int r=0;r<n;r++)
                        for(int c=0;c<n;c++)
                              s[i][j]+=temp[i+r][j+c];
                        s[i][j]/=n*n;
            }
            if(temp!=NULL)   {
                for(i=0;i<h+2;i++)
                    if(temp[i]!=NULL)
                        delete temp[i];
                    delete temp;
            }
        }
主站蜘蛛池模板: 聂荣县| 石门县| 双城市| 专栏| 南丰县| 嵊泗县| 渝北区| 潢川县| 景德镇市| 安图县| 大丰市| 滦平县| 宜州市| 陕西省| 班戈县| 利川市| 铁岭县| 永寿县| 彰武县| 伊通| 六盘水市| 调兵山市| 加查县| 开阳县| 逊克县| 成都市| 大丰市| 疏勒县| 双桥区| 庄浪县| 隆化县| 华容县| 积石山| 义马市| 凯里市| 蒙城县| 新营市| 定陶县| 千阳县| 陇南市| 自贡市|