6월17일 영상처리(히스토그램,2진화

2010. 6. 17. 09:472010년/6월


히스토그램이라고하면 기본적으로 색상의 분포도라고 생각하면된다. 
검은색이 많으면 그래프가 왼쪽으로 그려지고

반대로 화면에 흰색이많으면 오른쪽으로 그래프가 그려진다.



그래서 여러색상이 잇는 화면인경우 그래프가 골고루 그려진다


여기서 오른쪽으로 하나 치솟은 그래프는 내머리털 때문이다 -_-;;;
================================================================
================================================================
#include<Windows.h>
#include"vfw.h"

#include <math.h>
#include <iostream>


#pragma comment(lib, "vfw32.lib"//vfw32 라이브러리 포함

#define  SQRT1_2  0.70710678118654752440  //제곱근설정 
#define  PI   3.14159265358979323846  //파이설정

#define WIDTH4(width) ((width+3)>>2)<<2 // 폭설정
#define ID_BCAPTURE 101      //영상설정 

#define ZOOMSIZE 1.5    //크기설정

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //윈도우창 콜백 함수 
LRESULT CALLBACK FramInfo(HWND, LPVIDEOHDR); // 콜백 함수

TCHAR str[10];    //정수데이터값 확인을 위한 버퍼
unsigned char Menuflag;  //인터페이스 선택 

HINSTANCE g_hInst; //핸들
HWND hWndMain;  
HWND hVFW;
HWND Hwndmain;
HBITMAP hBit;    
BITMAPINFO Bm;    //비트맵 정보를 가짐
LPVIDEOHDR VideoHdr_1;
//영상 메모리
int Action;
int buf[256]={0,};

LPCTSTR lpszClass = TEXT("VFW 기본 예제");

BYTE *imageData;  //파일open한 이미지정보 받을 포인터
BITMAPFILEHEADER bmfh;  // 파일open한 비트맵파일해더 정보 
BITMAPINFO *binfo;    //파일open한 비트맵인포정보 
LONG width4;      //폭설정값 

// 변환할 정보
BITMAPINFO *chbinfo;  //크기 변경된 비트맵인포정보 
BYTE *chData;      //크기 변경된 비트맵DATA값 

BITMAPINFO* ChangeBitmapInfo(LONG width,LONG height,const BITMAPINFO* binfo,int i){
  
  BITMAPINFO* chbinfo; //24비트 용 비트맵인포 
  BITMAPINFO* blbinfo; //8비트 용 비트맵인포 
  LONG width4;
  
  if(i==24){ // 크기를 변환한 bitmapinfo구조체를 리턴해 준다.
    
    chbinfo = (BITMAPINFO *) malloc (sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256);
    //24비트 정보로 bitmapinfo를 설정
    chbinfo->bmiHeader.biBitCount = 24;
    chbinfo->bmiHeader.biClrImportant =binfo->bmiHeader.biClrImportant;
    chbinfo->bmiHeader.biClrUsed = binfo->bmiHeader.biClrUsed;
    chbinfo->bmiHeader.biCompression = binfo->bmiHeader.biCompression;
    chbinfo->bmiHeader.biHeight = height;
    chbinfo->bmiHeader.biPlanes = binfo->bmiHeader.biPlanes;
    chbinfo->bmiHeader.biSize =   binfo->bmiHeader.biSize;
    chbinfo->bmiHeader.biWidth = width;
    
    width4 = width *3;     //폭 맞춤
    width4 = ((width4+3)>>2)<<2;
    
    chbinfo->bmiHeader.biSizeImage = width4 * height;
    chbinfo->bmiHeader.biXPelsPerMeter = binfo->bmiHeader.biXPelsPerMeter;
    chbinfo->bmiHeader.biYPelsPerMeter = binfo->bmiHeader.biYPelsPerMeter;
    return  chbinfo;
  }
  else if(i==8)
  {
    blbinfo=(BITMAPINFO *) malloc (sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256);
    //8비트 정보로 bitmapinfo를설정 
    blbinfo->bmiHeader.biBitCount=8;
    blbinfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    blbinfo->bmiHeader.biWidth=width;
    blbinfo->bmiHeader.biHeight=height;
    
    width4=((width+3)>>2)<<2//폭설정
    
    blbinfo->bmiHeader.biXPelsPerMeter=0;
    blbinfo->bmiHeader.biYPelsPerMeter=0;
    blbinfo->bmiHeader.biSizeImage=width4*height;
    blbinfo->bmiHeader.biPlanes=1;
    blbinfo->bmiHeader.biClrUsed=256;
    blbinfo->bmiHeader.biCompression=0;
    blbinfo->bmiHeader.biClrImportant=256;
    for(i=0;i<256;++i)
    {
      blbinfo->bmiColors[i].rgbBlue=blbinfo->bmiColors[i].rgbGreen=blbinfo->bmiColors[i].rgbRed=i;
      blbinfo->bmiColors[i].rgbReserved=0;
    }
    
    return blbinfo;
  } 
  else 
  {
    MessageBox(0,"error","error",0);
    
  }
  return 0;
  
}
//선형보간으로 이미지 크기 변경 
BYTE* ReSizeImage(BITMAPINFO *binfo,const BITMAPINFO* cbinfo,const BYTE* Data,int i)
{
  
  
  BYTE newValue,R,G,B; //데이터값 
  BYTE* chData; //실제 데이터 넣을 포인터 
  int new_height=binfo->bmiHeader.biHeight;//새로운 이미지의 높이 계산 
  int new_width=binfo->bmiHeader.biWidth;//새로운 이미지의 폭 계산 
  int heightm1=cbinfo->bmiHeader.biHeight-1;
  int widthm1=cbinfo->bmiHeader.biWidth-1;
  int where,org_where;
  int r,c;//타겟 이미지 좌표 
  float r_orgr,r_orgc;//원 이미지 상의 해당 좌표 (실수값)
  int i_orgr,i_orgc;//원 이미지 상의 해당 좌표 (정수값)
  float sr,sc;// 예 1.24-1=0.24
  float I1,I2,I3,I4; //선형보간으로 얻는 값들 
  float zoominfactor = (float)binfo->bmiHeader.biWidth/cbinfo->bmiHeader.biWidth;
  unsigned int count=0;
  
  //Zoom Image를 위한 동적 메모리 할당
  // 원본이미지 폭 
  long width4 = binfo->bmiHeader.biWidth*3;
  width4 = WIDTH4(width4);
  
  // 수정되는 이미 폭 
  long cwidth4 = cbinfo->bmiHeader.biWidth * 3;
  cwidth4 = WIDTH4(cwidth4);
  
  //동적할당 
  chData=(BYTE* )malloc(binfo->bmiHeader.biSizeImage);
  
  //흑백일경우 
  if(i==8)
  {
    for(r=0;r<new_height;r++)
    {
      r =r;
      for(c=0;c<new_width;c++)
      {
        r_orgr=r/zoominfactor;
        r_orgc=c/zoominfactor;
        i_orgr=floor(r_orgr);//예: floor(2.8)=2.0
        i_orgc=floor(r_orgc);
        sr=r_orgr-i_orgr;
        sc=r_orgc-i_orgc;
        //범위 조사 
        //원이미지의 범위를 벗어나는 경우 0값 할당 
        if(i_orgr<0 || i_orgr>heightm1 || i_orgc<0 || i_orgc>widthm1)
        {
          where=r*width4/3+c;
          chData[where]=0;
          //  chData[where+1]=0;
          //  chData[where+2]=0;
          
        }
        //원 이미지의 범위 내에 존재 이중 선형 보간 수행 
        else
        { 
          count++;
          where=r*width4/3+c;
          
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+0]; //(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+0];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+0];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+0];//(org_r+1,org_c)
          
          //이중 선형 보간을 통한 새로운 밝기값 계산
          R=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          // newValue = (I1+I2+I3+I4)/4;
          //  chData[where]=newValue;
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+1];//(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+1];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+1];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+1];//(org_r+1,org_c)
          
          //이중 선형 보간을 통한 새로운 밝기값 계산
          G=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          //newValue = (I1+I2+I3+I4)/4;
          //chData[where+1]=newValue;
          
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+2];//(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+2];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+2];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+2];//(org_r+1,org_c)
          
          //이중 선형 보간을 통한 새로운 밝기값 계산
          B=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          //newValue = (I1+I2+I3+I4)/4;  //이중 선형 보간을 안할시 test 코드
          //chData[where+2]=newValue; 
          chData[where]=(R+G+B)/3;
        }
      }
    }
  }
  //24비트 칼라일경우 
  else if(i==24)
  {
    for(r=0;r<new_height;r++)
    {
      r =r;
      for(c=0;c<new_width;c++)
      {
        r_orgr=r/zoominfactor;
        r_orgc=c/zoominfactor;
        i_orgr=floor(r_orgr);//예: floor(2.8)=2.0
        i_orgc=floor(r_orgc);
        sr=r_orgr-i_orgr;
        sc=r_orgc-i_orgc;
        //범위 조사 
        //원이미지의 범위를 벗어나는 경우 0값 할당 
        if(i_orgr<0 || i_orgr>heightm1 || i_orgc<0 || i_orgc>widthm1)
        {
          where=r*width4+c*3;
          chData[where]=0;
          chData[where+1]=0;
          chData[where+2]=0;
        }
        //원 이미지의 범위 내에 존재 이중 선형 보간 수행 
        else
        { 
          count++;
          where=r*width4+c*3;
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+0]; //(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+0];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+0];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+0];//(org_r+1,org_c)
          //이중 선형 보간을 통한 새로운 밝기값 계산
          newValue=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          // newValue = (I1+I2+I3+I4)/4;
          chData[where]=newValue;
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+1];//(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+1];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+1];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+1];//(org_r+1,org_c)
          
          //이중 선형 보간을 통한 새로운 밝기값 계산
          newValue=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          //newValue = (I1+I2+I3+I4)/4;
          chData[where+1]=newValue;
          
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+2];//(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+2];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+2];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+2];//(org_r+1,org_c)
          
          //이중 선형 보간을 통한 새로운 밝기값 계산
          newValue=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          //newValue = (I1+I2+I3+I4)/4;  //이중 선형 보간을 안할시 test 코드
          chData[where+2]=newValue; 
        }
      }
    }
  }
  return chData;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCndParam, int nCmdShow)
{
  HWND hWnd;
  MSG Message;
  WNDCLASS WndClass;
  g_hInst = hInstance;
  
  WndClass.cbClsExtra = 0;
  WndClass.cbWndExtra = 0;
  WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  WndClass.hInstance = hInstance;
  WndClass.lpfnWndProc = WndProc;
  WndClass.lpszClassName = lpszClass;
  WndClass.lpszMenuName = NULL;
  WndClass.style = CS_HREDRAW|CS_VREDRAW;
  
  RegisterClass(&WndClass);
  
  //영상을 보여줄 윈도우 생성
  
  
  
  hWnd = CreateWindow(lpszClass, lpszClass,WS_OVERLAPPEDWINDOW|WS_CAPTION,200,200
    300300, NULL, (HMENU)NULL, hInstance, NULL); 
  
  hWndMain = hWnd;
  ShowWindow(hWnd, SW_SHOW);
  
  
  while(GetMessage(&Message, 0,0,0))
  {
    TranslateMessage(&Message);
    DispatchMessage(&Message);
  }
  return (int)Message.wParam;
  
}



LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
  HDC Hdc;
  FILE *file;
  LONG width, height;
  int count=0;
  
  switch(iMessage)
  {
  case WM_CREATE:
    
    Hwndmain = hWnd;
    
    Hdc = GetDC(hWnd);
    hVFW = capCreateCaptureWindow(TEXT("VFW"), WS_CHILD|WS_VISIBLE,0,0,1,1,hWnd,0);
    //(캡쳐될 윈도우 이름 생성, 윈도우 스타일, 시작점x좌표, 시작점y좌표, 넓이, 높이, 부모윈도우 핸들, window ID)
    
    capDriverConnect(hVFW,0);  //캡쳐윈도우와 드라이버 연결(캡쳐윈도우 핸들, 캡쳐드라이버의 인덱스)
    capPreviewRate(hVFW,1);  //프리뷰모드에서 보여질 프레임 속도(rate)설정 
    //capPreview(hVFW,TRUE);   //프리뷰모드 사용여부
    capGetVideoFormat(hVFW, &Bm, sizeof(Bm)); //영상복사를 위해 사용, 포맷의 크기를 바이트로 전환
    //(캡쳐윈도우 핸들, bitmapinfo 구조체 포인터, 구조체 크기)
    
    hBit = CreateCompatibleBitmap(Hdc, Bm.bmiHeader.biWidth, Bm.bmiHeader.biHeight);
    //DC에 호환하는 비트맵을 생성하여 반환(dc의 핸들, 비트맵의가로 사이즈, 비트맵의 세로 사이즈)
    
    // 비디오 프레임이 캡쳐되었을 경우 처리하기 위한 함수를 설정해주는 매크로 함수
    if(capSetCallbackOnFrame(hVFW, FramInfo)==FALSE)
      //(캡쳐 윈도우 핸들, 콜백함수에 의해 호출되는 함수 포인터)
    {
      return FALSE;
    }
    
    
    
    ReleaseDC(hWnd, Hdc);
    return 0;
  case WM_COMMAND: 
    return 0;
  case WM_LBUTTONDOWN:
    Hdc = GetDC(hWnd);
    
    width = (unsigned int)binfo->bmiHeader.biWidth;
    height = (unsigned int)binfo->bmiHeader.biHeight;
    
    //window창 위치와 크기 설정 
    MoveWindow(hWndMain,200,200,width*2+15,height,true);
    
    SetDIBitsToDevice(Hdc,0,0,width,height,
      NULL,NULL,NULL,height,imageData,
      binfo,DIB_RGB_COLORS);
    
    if(chData!=NULL){
      SetDIBitsToDevice(Hdc,width+5,0,chbinfo->bmiHeader.biWidth,chbinfo->bmiHeader.biHeight,
        NULL,NULL,NULL,chbinfo->bmiHeader.biHeight,chData,
        chbinfo,DIB_RGB_COLORS);
    }
    ReleaseDC(hWnd,Hdc);
    return 0;
  case WM_DESTROY:
    if(chData!=NULL){
      free(chData);
      chData=NULL;
    }  
    if(imageData!=NULL){
      free(imageData);
      imageData =NULL;
    }
    free(binfo);
    PostQuitMessage(0);
    return 0;
  }
  return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}
LRESULT CALLBACK FramInfo(HWND hVFW, LPVIDEOHDR VideoHdr)
{
  
  int i;
  int j;
  int sel;
  HDC Hdc;
  HDC hMemDC;    //메모리DC
  HBITMAP OldBitmap;
  
  int height, width;
  //비트맵 영상 정보
  //영상출력을 위한 변수
  
  capPreviewRate(hVFW, 0);   //프리뷰모드에서 보여질 프레임 속도를 0으로 설정함
  
  // 즉 어떠한 처리가 다 끝나기 전에는 다시 콜백함수가 호출되게 하지 않는다
  LONG chwidth,chheight;
  
  //수정할 이미지 크기 
  chwidth = 256;
  chheight = Bm.bmiHeader.biHeight; 
  
  
  //bitmapinfo의 size를 바꾸어서 받아온다.
  chbinfo = ChangeBitmapInfo(chwidth,chheight,&Bm,8);
//  chData = ReSizeImage(chbinfo,&Bm,VideoHdr->lpData,8);   

  width4=Bm.bmiHeader.biWidth*3;
  width4=WIDTH4(width4);


  for(i=0;i<Bm.bmiHeader.biHeight;++i)
  {
    for(j=0;j<Bm.bmiHeader.biWidth;++j)
    {
      sel=((VideoHdr->lpData[i*width4+j*3])+(VideoHdr->lpData[i*width4+j*3+1])+(VideoHdr->lpData[i*width4+j*3+2]))/3;
      buf[sel]++;
    }

  }
  
  width4=chbinfo->bmiHeader.biWidth;
  width4=WIDTH4(width4);
  chData =(BYTE *)malloc(chbinfo->bmiHeader.biSizeImage);
  for(i=0;i<chwidth;++i)
  {
    for(j=0;j<chbinfo->bmiHeader.biHeight;++j)
    {
      if(buf[i]==0)
      {
        chData[j*width4+i]=255;
      }
      else
      {
        chData[j*width4+i]=0;
      }
      buf[i]--;
    }
    
  }
  
  
  height = Bm.bmiHeader.biHeight;  //캡쳐영상의 세로
  width = Bm.bmiHeader.biWidth;  //캡쳐영상의 가로
  
  Hdc=GetDC(Hwndmain);
  hMemDC = CreateCompatibleDC(Hdc);
  OldBitmap = (HBITMAP)SelectObject(hMemDC,hBit);
  MoveWindow(hWndMain,200,200,width+200,height*2+80,true);
  
  SetDIBitsToDevice(Hdc,0,0,width,height,NULL,NULL,NULL,height,VideoHdr->lpData,&Bm,DIB_RGB_COLORS);
    SetDIBitsToDevice(Hdc,0,height,256,height,NULL,NULL,NULL,height,chData,chbinfo,DIB_RGB_COLORS);
  
  
  SelectObject(hMemDC, OldBitmap);
  DeleteDC(hMemDC);
  ReleaseDC(Hwndmain, Hdc); 
  capPreviewRate(hVFW,1); //다음 프레임에는 다시 영상처리를 시작 하게 된다.
  
  return 0;
}

===================================================================
===================================================================
영상의 2진화
프로그램을 영상의 값을  128보다 크면 검은색 128보다 작으면 0의 값을 넣어준다.



이경우 색은 흰색과 검은색으로 나온다. 바로 2진화라고 한다.
결국에 두색으로 보여주기때문에 0아니면 1 값같이 나와서 영상을 간단하게 본다.

#include "soullex.h"

#pragma comment(lib, "vfw32.lib"//vfw32 라이브러리 포함

#define  SQRT1_2  0.70710678118654752440  //제곱근설정 
#define  PI   3.14159265358979323846  //파이설정


#define ID_BCAPTURE 101      //영상설정 

#define ZOOMSIZE 1.5    //크기설정

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //윈도우창 콜백 함수 
LRESULT CALLBACK FramInfo(HWND, LPVIDEOHDR); // 콜백 함수

TCHAR str[10];    //정수데이터값 확인을 위한 버퍼
unsigned char Menuflag;  //인터페이스 선택 

HINSTANCE g_hInst; //핸들
HWND hWndMain;  
HWND hVFW;
HWND Hwndmain;
HBITMAP hBit;    
BITMAPINFO Bm;    //비트맵 정보를 가짐
LPVIDEOHDR VideoHdr_1;
//영상 메모리
int Action;
int buf[256]={0,};

LPCTSTR lpszClass = TEXT("VFW 기본 예제");

BYTE *imageData;  //파일open한 이미지정보 받을 포인터
BITMAPFILEHEADER bmfh;  // 파일open한 비트맵파일해더 정보 
BITMAPINFO *binfo;    //파일open한 비트맵인포정보 
LONG width4;      //폭설정값 

// 변환할 정보
BITMAPINFO *chbinfo;  //크기 변경된 비트맵인포정보 
BYTE *chData;      //크기 변경된 비트맵DATA값 


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCndParam, int nCmdShow)
{
  HWND hWnd;
  MSG Message;
  WNDCLASS WndClass;
  g_hInst = hInstance;
  
  WndClass.cbClsExtra = 0;
  WndClass.cbWndExtra = 0;
  WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  WndClass.hInstance = hInstance;
  WndClass.lpfnWndProc = WndProc;
  WndClass.lpszClassName = lpszClass;
  WndClass.lpszMenuName = NULL;
  WndClass.style = CS_HREDRAW|CS_VREDRAW;
  
  RegisterClass(&WndClass);
  
  //영상을 보여줄 윈도우 생성
  
  
  
  hWnd = CreateWindow(lpszClass, lpszClass,WS_OVERLAPPEDWINDOW|WS_CAPTION,200,200
    300300, NULL, (HMENU)NULL, hInstance, NULL); 
  
  hWndMain = hWnd;
  ShowWindow(hWnd, SW_SHOW);
  
  
  while(GetMessage(&Message, 0,0,0))
  {
    TranslateMessage(&Message);
    DispatchMessage(&Message);
  }
  return (int)Message.wParam;
  
}



LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
  HDC Hdc;
  FILE *file;
  LONG width, height;
  int count=0;
    LONG chwidth,chheight;
  
  switch(iMessage)
  {
  case WM_CREATE:
    
    Hwndmain = hWnd;
    
    Hdc = GetDC(hWnd);
    hVFW = capCreateCaptureWindow(TEXT("VFW"), WS_CHILD|WS_VISIBLE,0,0,1,1,hWnd,0);
    //(캡쳐될 윈도우 이름 생성, 윈도우 스타일, 시작점x좌표, 시작점y좌표, 넓이, 높이, 부모윈도우 핸들, window ID)
    
    capDriverConnect(hVFW,0);  //캡쳐윈도우와 드라이버 연결(캡쳐윈도우 핸들, 캡쳐드라이버의 인덱스)
    capPreviewRate(hVFW,1);  //프리뷰모드에서 보여질 프레임 속도(rate)설정 
    //capPreview(hVFW,TRUE);   //프리뷰모드 사용여부
    capGetVideoFormat(hVFW, &Bm, sizeof(Bm)); //영상복사를 위해 사용, 포맷의 크기를 바이트로 전환
    //(캡쳐윈도우 핸들, bitmapinfo 구조체 포인터, 구조체 크기)
    
    hBit = CreateCompatibleBitmap(Hdc, Bm.bmiHeader.biWidth, Bm.bmiHeader.biHeight);
    //DC에 호환하는 비트맵을 생성하여 반환(dc의 핸들, 비트맵의가로 사이즈, 비트맵의 세로 사이즈)
    chwidth = Bm.bmiHeader.biWidth;
    chheight = Bm.bmiHeader.biHeight; 
    chbinfo = ChangeBitmapInfo(chwidth,chheight,&Bm,8);
    chData =(BYTE *)malloc(chbinfo->bmiHeader.biSizeImage);
    // 비디오 프레임이 캡쳐되었을 경우 처리하기 위한 함수를 설정해주는 매크로 함수
    if(capSetCallbackOnFrame(hVFW, FramInfo)==FALSE)
      //(캡쳐 윈도우 핸들, 콜백함수에 의해 호출되는 함수 포인터)
    {
      return FALSE;
    }
    
    
    
    ReleaseDC(hWnd, Hdc);
    return 0;
  case WM_COMMAND: 
    return 0;
  case WM_LBUTTONDOWN:
    Hdc = GetDC(hWnd);
    
    width = (unsigned int)binfo->bmiHeader.biWidth;
    height = (unsigned int)binfo->bmiHeader.biHeight;
    
    //window창 위치와 크기 설정 
    MoveWindow(hWndMain,200,200,width*2+15,height,true);
    
/*
    SetDIBitsToDevice(Hdc,0,0,width,height,
      NULL,NULL,NULL,height,imageData,
      binfo,DIB_RGB_COLORS);
    
    if(chData!=NULL){
      SetDIBitsToDevice(Hdc,width+5,0,chbinfo->bmiHeader.biWidth,chbinfo->bmiHeader.biHeight,
        NULL,NULL,NULL,chbinfo->bmiHeader.biHeight,chData,
        chbinfo,DIB_RGB_COLORS);
    }
    */

    ReleaseDC(hWnd,Hdc);
    return 0;
  case WM_DESTROY:
    if(chData!=NULL){
    //  free(chData);
      chData=NULL;
    }  
    if(imageData!=NULL){
      free(imageData);
      imageData =NULL;
    }
    free(binfo);
    PostQuitMessage(0);
    return 0;
  }
  return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}
LRESULT CALLBACK FramInfo(HWND hVFW, LPVIDEOHDR VideoHdr)
{
  
  int i;
  int j;
  int sel;
  long width5;
  HDC Hdc;
  HDC hMemDC;    //메모리DC
  HBITMAP OldBitmap;
  
  int height, width;
  //비트맵 영상 정보
  //영상출력을 위한 변수
  
  capPreviewRate(hVFW, 0);   //프리뷰모드에서 보여질 프레임 속도를 0으로 설정함
  
  // 즉 어떠한 처리가 다 끝나기 전에는 다시 콜백함수가 호출되게 하지 않는다

  
  //수정할 이미지 크기 


    
  //bitmapinfo의 size를 바꾸어서 받아온다.

  width4=Bm.bmiHeader.biWidth*3;
  width4=WIDTH4(width4);
  
  width5=chbinfo->bmiHeader.biWidth;
  width5=WIDTH4(width5);
  
  for(i=0;i<Bm.bmiHeader.biHeight;++i)
  {
    for(j=0;j<Bm.bmiHeader.biWidth;++j)
    {
      sel=((VideoHdr->lpData[i*width4+j*3])+(VideoHdr->lpData[i*width4+j*3+1])+(VideoHdr->lpData[i*width4+j*3+2]))/3;
      
      if(sel<128)
      {
        chData[i*width5+j]=0;
      }
      else
      {
        chData[i*width5+j]=255;
      }

      

    }

  }
  
  height = Bm.bmiHeader.biHeight;  //캡쳐영상의 세로
  width = Bm.bmiHeader.biWidth;  //캡쳐영상의 가로
  
  Hdc=GetDC(Hwndmain);
  hMemDC = CreateCompatibleDC(Hdc);
  OldBitmap = (HBITMAP)SelectObject(hMemDC,hBit);
  MoveWindow(hWndMain,200,200,width+200,height*2+80,true);
  
  SetDIBitsToDevice(Hdc,0,0,width,height,NULL,NULL,NULL,height,VideoHdr->lpData,&Bm,DIB_RGB_COLORS);
    SetDIBitsToDevice(Hdc,0,height,width,height,NULL,NULL,NULL,height,chData,chbinfo,DIB_RGB_COLORS);
    

  
  SelectObject(hMemDC, OldBitmap);
  DeleteDC(hMemDC);
  ReleaseDC(Hwndmain, Hdc); 
  capPreviewRate(hVFW,1); //다음 프레임에는 다시 영상처리를 시작 하게 된다.
  
  return 0;
 }

==================================================================
==================================================================
soullex.h 부분
#include <math.h>
#include <iostream>
#include<Windows.h>
#include"vfw.h"

#define WIDTH4(width) ((width+3)>>2)<<2 // 폭설정
BITMAPINFO* ChangeBitmapInfo(LONG width,LONG height,const BITMAPINFO* binfo,int i){
  
  BITMAPINFO* chbinfo; //24비트 용 비트맵인포 
  BITMAPINFO* blbinfo; //8비트 용 비트맵인포 
  LONG width4;
  
  if(i==24){ // 크기를 변환한 bitmapinfo구조체를 리턴해 준다.
    
    chbinfo = (BITMAPINFO *) malloc (sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256);
    //24비트 정보로 bitmapinfo를 설정
    chbinfo->bmiHeader.biBitCount = 24;
    chbinfo->bmiHeader.biClrImportant =binfo->bmiHeader.biClrImportant;
    chbinfo->bmiHeader.biClrUsed = binfo->bmiHeader.biClrUsed;
    chbinfo->bmiHeader.biCompression = binfo->bmiHeader.biCompression;
    chbinfo->bmiHeader.biHeight = height;
    chbinfo->bmiHeader.biPlanes = binfo->bmiHeader.biPlanes;
    chbinfo->bmiHeader.biSize =   binfo->bmiHeader.biSize;
    chbinfo->bmiHeader.biWidth = width;
    
    width4 = width *3;     //폭 맞춤
    width4 = ((width4+3)>>2)<<2;
    
    chbinfo->bmiHeader.biSizeImage = width4 * height;
    chbinfo->bmiHeader.biXPelsPerMeter = binfo->bmiHeader.biXPelsPerMeter;
    chbinfo->bmiHeader.biYPelsPerMeter = binfo->bmiHeader.biYPelsPerMeter;
    return  chbinfo;
  }
  else if(i==8)
  {
    blbinfo=(BITMAPINFO *) malloc (sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256);
    //8비트 정보로 bitmapinfo를설정 
    blbinfo->bmiHeader.biBitCount=8;
    blbinfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    blbinfo->bmiHeader.biWidth=width;
    blbinfo->bmiHeader.biHeight=height;
    
    width4=((width+3)>>2)<<2//폭설정
    
    blbinfo->bmiHeader.biXPelsPerMeter=0;
    blbinfo->bmiHeader.biYPelsPerMeter=0;
    blbinfo->bmiHeader.biSizeImage=width4*height;
    blbinfo->bmiHeader.biPlanes=1;
    blbinfo->bmiHeader.biClrUsed=256;
    blbinfo->bmiHeader.biCompression=0;
    blbinfo->bmiHeader.biClrImportant=256;
    for(i=0;i<256;++i)
    {
      blbinfo->bmiColors[i].rgbBlue=blbinfo->bmiColors[i].rgbGreen=blbinfo->bmiColors[i].rgbRed=i;
      blbinfo->bmiColors[i].rgbReserved=0;
    }
    
    return blbinfo;
  } 
  else 
  {
    MessageBox(0,"error","error",0);
    
  }
  return 0;
  
}
//선형보간으로 이미지 크기 변경 
BYTE* ReSizeImage(BITMAPINFO *binfo,const BITMAPINFO* cbinfo,const BYTE* Data,int i)
{
  
  
  BYTE newValue,R,G,B; //데이터값 
  BYTE* chData; //실제 데이터 넣을 포인터 
  int new_height=binfo->bmiHeader.biHeight;//새로운 이미지의 높이 계산 
  int new_width=binfo->bmiHeader.biWidth;//새로운 이미지의 폭 계산 
  int heightm1=cbinfo->bmiHeader.biHeight-1;
  int widthm1=cbinfo->bmiHeader.biWidth-1;
  int where,org_where;
  int r,c;//타겟 이미지 좌표 
  float r_orgr,r_orgc;//원 이미지 상의 해당 좌표 (실수값)
  int i_orgr,i_orgc;//원 이미지 상의 해당 좌표 (정수값)
  float sr,sc;// 예 1.24-1=0.24
  float I1,I2,I3,I4; //선형보간으로 얻는 값들 
  float zoominfactor = (float)binfo->bmiHeader.biWidth/cbinfo->bmiHeader.biWidth;
  unsigned int count=0;
  
  //Zoom Image를 위한 동적 메모리 할당
  // 원본이미지 폭 
  long width4 = binfo->bmiHeader.biWidth*3;
  width4 = WIDTH4(width4);
  
  // 수정되는 이미 폭 
  long cwidth4 = cbinfo->bmiHeader.biWidth * 3;
  cwidth4 = WIDTH4(cwidth4);
  
  //동적할당 
  chData=(BYTE* )malloc(binfo->bmiHeader.biSizeImage);
  
  //흑백일경우 
  if(i==8)
  {
    for(r=0;r<new_height;r++)
    {
      r =r;
      for(c=0;c<new_width;c++)
      {
        r_orgr=r/zoominfactor;
        r_orgc=c/zoominfactor;
        i_orgr=floor(r_orgr);//예: floor(2.8)=2.0
        i_orgc=floor(r_orgc);
        sr=r_orgr-i_orgr;
        sc=r_orgc-i_orgc;
        //범위 조사 
        //원이미지의 범위를 벗어나는 경우 0값 할당 
        if(i_orgr<0 || i_orgr>heightm1 || i_orgc<0 || i_orgc>widthm1)
        {
          where=r*width4/3+c;
          chData[where]=0;
          //  chData[where+1]=0;
          //  chData[where+2]=0;
          
        }
        //원 이미지의 범위 내에 존재 이중 선형 보간 수행 
        else
        { 
          count++;
          where=r*width4/3+c;
          
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+0]; //(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+0];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+0];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+0];//(org_r+1,org_c)
          
          //이중 선형 보간을 통한 새로운 밝기값 계산
          R=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          // newValue = (I1+I2+I3+I4)/4;
          //  chData[where]=newValue;
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+1];//(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+1];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+1];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+1];//(org_r+1,org_c)
          
          //이중 선형 보간을 통한 새로운 밝기값 계산
          G=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          //newValue = (I1+I2+I3+I4)/4;
          //chData[where+1]=newValue;
          
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+2];//(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+2];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+2];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+2];//(org_r+1,org_c)
          
          //이중 선형 보간을 통한 새로운 밝기값 계산
          B=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          //newValue = (I1+I2+I3+I4)/4;  //이중 선형 보간을 안할시 test 코드
          //chData[where+2]=newValue; 
          chData[where]=(R+G+B)/3;
        }
      }
    }
  }
  //24비트 칼라일경우 
  else if(i==24)
  {
    for(r=0;r<new_height;r++)
    {
      r =r;
      for(c=0;c<new_width;c++)
      {
        r_orgr=r/zoominfactor;
        r_orgc=c/zoominfactor;
        i_orgr=floor(r_orgr);//예: floor(2.8)=2.0
        i_orgc=floor(r_orgc);
        sr=r_orgr-i_orgr;
        sc=r_orgc-i_orgc;
        //범위 조사 
        //원이미지의 범위를 벗어나는 경우 0값 할당 
        if(i_orgr<0 || i_orgr>heightm1 || i_orgc<0 || i_orgc>widthm1)
        {
          where=r*width4+c*3;
          chData[where]=0;
          chData[where+1]=0;
          chData[where+2]=0;
        }
        //원 이미지의 범위 내에 존재 이중 선형 보간 수행 
        else
        { 
          count++;
          where=r*width4+c*3;
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+0]; //(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+0];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+0];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+0];//(org_r+1,org_c)
          //이중 선형 보간을 통한 새로운 밝기값 계산
          newValue=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          // newValue = (I1+I2+I3+I4)/4;
          chData[where]=newValue;
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+1];//(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+1];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+1];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+1];//(org_r+1,org_c)
          
          //이중 선형 보간을 통한 새로운 밝기값 계산
          newValue=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          //newValue = (I1+I2+I3+I4)/4;
          chData[where+1]=newValue;
          
          
          I1=(float)Data[(cwidth4*i_orgr)+i_orgc*3+2];//(org_r,org_c)
          I2=(float)Data[(cwidth4*i_orgr)+(i_orgc+1)*3+2];//(org_r,org_c+1)
          I3=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+2];//(org_r+1,org_c+1)
          I4=(float)Data[(cwidth4*(i_orgr+1))+(i_orgc+1)*3+2];//(org_r+1,org_c)
          
          //이중 선형 보간을 통한 새로운 밝기값 계산
          newValue=(BYTE)(I1*(1-sc)*(1-sr)+I2*sc*(1-sr)+I3*sc*sr+I4*(1-sc)*sr);
          //newValue = (I1+I2+I3+I4)/4;  //이중 선형 보간을 안할시 test 코드
          chData[where+2]=newValue; 
        }
      }
    }
  }
  return chData;
}
======================================================================
=====================================================================

RGB=>YIQ로


==================================================================
==================================================================