2013年6月9日 星期日

98360242_張綉美_上機考心得


#include <stdio.h>
#include <cv.h>
#include <highgui.h>
#include <cvcam.h>

#define refBlue 255
#define refGreen 255
#define refRed 255

#define TH 150  //門檻值

int main()
{
    CvCapture *capture;
    IplImage *frame;
    IplImage *img;
    IplImage *grey;
   
    IplImage *logoImg;
    IplImage *logoImg2;
   
    float SkinPixelNumber;
    float SkinPixelX;
    float SkinPixelY;
    int MouseX=0,MouseY=0;
   
    logoImg=cvLoadImage("images.jpg");
    logoImg2=cvLoadImage("images2.jpg");
   
 
   
    capture=cvCreateCameraCapture( 0 );
    frame = cvQueryFrame(capture);
    grey = cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 1);
    img = cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 3);
   
    while(1)
    {
        frame = cvQueryFrame(capture);                                        
        cvCvtColor(frame, frame, CV_BGR2YCrCb);
        cvInRangeS(frame, cvScalar(0,137,77), cvScalar(256,177,127),grey); //判斷膚色轉換成黑白影像
        frame = cvQueryFrame(capture); //在抓一次原的視訊影像
        cvLine(frame,cvPoint(frame->width/2,0),cvPoint(frame->width/2,frame->height),CV_RGB(255,0,0),5,8,0);
//畫線 X軸的一半位置 和Y軸0的位置 到  X軸的一半位置 和Y軸的全高
           for (int y=0; y<logoImg->height; y++) {   //讀取
           uchar* ptr1=(uchar*) (logoImg->imageData +y*logoImg->widthStep);
           uchar* ptr2=(uchar*) (frame->imageData +(y)*frame->widthStep);
         
  for (int x=0; x<logoImg->width; x++) {
                  int D= (ptr1[3*x] - refBlue) * (ptr1[3*x] - refBlue) +       // 計算白色色彩值範圍
                  (ptr1[3*x+1] - refGreen) * (ptr1[3*x+1] -refGreen) +
                  (ptr1[3*x+2] - refRed) * (ptr1[3*x+2] - refRed);

             if(sqrt(D) > TH){             //開根號讓數值大於門檻值的部分顯示 去除背景
           ptr2[3*(x+50)]=ptr1[3*(x)] ;
           ptr2[3*(x+50)+1]=ptr1[3*(x)+1] ;
           ptr2[3*(x+50)+2]=ptr1[3*(x)+2] ;
           }  
           }
           }
         
           for (int y=0; y<logoImg2->height; y++) {
           uchar* ptr1=(uchar*) (logoImg2->imageData +y*logoImg2->widthStep);
           uchar* ptr2=(uchar*) (frame->imageData +(y)*frame->widthStep);
           for (int x=0; x<logoImg2->width; x++) {    
               int D= (ptr1[3*x] - refBlue) * (ptr1[3*x] - refBlue) +
                  (ptr1[3*x+1] - refGreen) * (ptr1[3*x+1] -refGreen) +
                  (ptr1[3*x+2] - refRed) * (ptr1[3*x+2] - refRed);
                 
               if(sqrt(D) > TH){  
           ptr2[3*(x+215)]=ptr1[3*(x)] ;
           ptr2[3*(x+215)+1]=ptr1[3*(x)+1] ;
           ptr2[3*(x+215)+2]=ptr1[3*(x)+2] ;  
           }
           }
           }    

       
        for (int y=0; y<grey->height; y++) {
        uchar* ptr1=(uchar*) (frame->imageData +y*frame->widthStep);
        uchar* ptr2=(uchar*) (grey->imageData +y*grey->widthStep);
       
        for (int x=0; x<grey->width; x++) {
            if(ptr2[x]==255) {
            SkinPixelNumber++;
            SkinPixelX+=x;
            SkinPixelY+=y;
            }
//計算所有膚色值將x,y值總數相加
           
         }
         }
          if (SkinPixelNumber>0) { //抓膚色的中心點
          MouseX=(int)(SkinPixelX/SkinPixelNumber);
          MouseY=(int)(SkinPixelY/SkinPixelNumber)-120.0;
          }      
       
         for (int y=0; y<logoImg->height; y++) {
           uchar* ptr1=(uchar*) (logoImg->imageData +y*logoImg->widthStep);
           uchar* ptr2=(uchar*) (frame->imageData +(y+MouseY)*frame->widthStep);
           for (int x=0; x<logoImg->width; x++) {    
               int D= (ptr1[3*x] - refBlue) * (ptr1[3*x] - refBlue) +
                  (ptr1[3*x+1] - refGreen) * (ptr1[3*x+1] -refGreen) +
                  (ptr1[3*x+2] - refRed) * (ptr1[3*x+2] - refRed);
                 
               if(MouseX < 150)if(sqrt(D) > TH){    //判斷虛擬滑鼠小於視窗大小150時顯示左邊的圖片
           ptr2[3*(x+MouseX-50)]=ptr1[3*(x)] ;
           ptr2[3*(x+MouseX-50)+1]=ptr1[3*(x)+1] ;
           ptr2[3*(x+MouseX-50)+2]=ptr1[3*(x)+2] ;  
           }
           }
           }  
 
           for (int y=0; y<logoImg2->height; y++) {
           uchar* ptr1=(uchar*) (logoImg2->imageData +y*logoImg2->widthStep);
           uchar* ptr2=(uchar*) (frame->imageData +(y+MouseY)*frame->widthStep);
           for (int x=0; x<logoImg2->width; x++) {    
               int D= (ptr1[3*x] - refBlue) * (ptr1[3*x] - refBlue) +
                  (ptr1[3*x+1] - refGreen) * (ptr1[3*x+1] -refGreen) +
                  (ptr1[3*x+2] - refRed) * (ptr1[3*x+2] - refRed);
                 
               if(MouseX > 150)if(sqrt(D) > TH){    //判斷虛擬滑鼠大於視窗大小150時顯示右邊的圖片
           ptr2[3*(x+MouseX)]=ptr1[3*(x)] ;
           ptr2[3*(x+MouseX)+1]=ptr1[3*(x)+1] ;
           ptr2[3*(x+MouseX)+2]=ptr1[3*(x)+2] ;  
         
           }
           }  
           }
         

        cvShowImage("Webcam", frame);
        cvShowImage("98360242", grey);
       
        SkinPixelNumber=0;
        SkinPixelX=0;
        SkinPixelY=0;
       
        cvWaitKey(20);
       
       
    }
    cvReleaseCapture(&capture);
    cvDestroyWindow("Webcam");
}



試後心得:
臨時抱佛腳的後果就是題目一下來完全不曉得該從何著手,最一開始畫線的部分只曉得要用cvLine卻忘了做長與寬位置的調整,所以線畫出來一直是歪的,不符合題目需求,考試過程最後也只有把圖片放到虛擬滑鼠上,但尚未做判斷,所以無法讓圖片跟著頭移動而變換皇冠。
考試結束,詢問有成功的同學了解題最主要目的,其實加入我們需要的材料後只要靠一些判斷及調整就可以完成。在找中心點時,只要一超出範圍就會不能run,所以在測試很多遍後想到可以在MouseY=(int)(SkinPixelY/SkinPixelNumber)這裡做更改,只要在後面-120.0就可以解決讓圖片改在中心點向上移動的位置的問題。放入圖片及去背後,因為我們是要讓圖片在左右兩邊做更動,所以設定MouseX小於視窗的一半為左邊,大於一半的範圍即為右邊,將這些基本設定都解決完畢後我的戴皇冠終於完成。

沒有留言:

張貼留言