본문 바로가기
코스웨어/15년 스마트컨트롤러

20151125 - 홍준모 업무일지 영상처리 10일째 - 배경처리(알파값 : ex)일기 예보)

by 알 수 없는 사용자 2015. 11. 25.
728x90
반응형

우선.. 삽질하다가 원본 사진 명암값 그래프 출력하도록만 만들었다 R,G,B 값 추출해서 그래프 출력할 수 있도록 하자.














일기 예보







일기 예보할 때 캐스터가 지도가 없지만 있는것처럼 연기하며 설명하는데 이때 이 영상처리는 어떻게 하는지.

그 배경을 비트맵으로 입히는데 이렇게 하려면 특정한 칠판 색깔을 찾아 내야 한다.



memcpy() 를 대체하기위해 헤더 데이터 값에서 바로 가져온 소스


LRESULT CALLBACK Capture(HWND hWpWnd, LPVIDEOHDR lpVHdr)
{
  HDC hdc;
  int iCountX;
  int iCountY;
  WCHAR wcStr[50= { 0, };
  static BYTE vData[X_SCALE * Y_SCALE * 3];  //영상처리를 위해서 데이터 값을 그대로 가져올 것.

  hdc = GetDC(hWnd);

  //memcpy(vData, lpVHdr->lpData, lpVHdr->dwBufferLength);
  for (iCountY = 0; iCountY < Y_SCALE; ++iCountY)
  {
    for (iCountX = 0; iCountX < X_SCALE; ++iCountX)
    {
      vData[(iCountY * X_SCALE + iCountX) * 3 + 0= lpVHdr->lpData[(iCountY * X_SCALE + iCountX) * 3 + 0];
      vData[(iCountY * X_SCALE + iCountX) * 3 + 1= lpVHdr->lpData[(iCountY * X_SCALE + iCountX) * 3 + 1];
      vData[(iCountY * X_SCALE + iCountX) * 3 + 2= lpVHdr->lpData[(iCountY * X_SCALE + iCountX) * 3 + 2];
    }
  }
  StretchDIBits(hdc, X_SCALE, 0, X_SCALE, Y_SCALE, 00, X_SCALE, Y_SCALE, vData, &stBmpInfo, DIB_RGB_COLORS, SRCCOPY);

  /*
  memcpy(vData, lpVHdr->lpData, lpVHdr->dwBufferLength);
  for (iCountY = 0; iCountY < Y_SCALE; ++iCountY)
  {
    for (iCountX = 0; iCountX < X_SCALE; ++iCountX)
    {
      //*(vData + (iCountY * X_SCALE + iCountX) * 3 + 0) = 0;
      *(vData + (iCountY * X_SCALE + iCountX) * 3 + 1) = 0;
      *(vData + (iCountY * X_SCALE + iCountX) * 3 + 2) = 0;
    }
  }
  StretchDIBits(hdc, X_SCALE, Y_SCALE, X_SCALE, Y_SCALE, 0, 0, X_SCALE, Y_SCALE, vData, &stBmpInfo, DIB_RGB_COLORS, SRCCOPY);
  */

  ReleaseDC(hWnd, hdc);

  return;
}













아마 현재 


// 영상 정보 편집 // 시작--------------------------------------------

ucpPixel = BMbuf + stpBFH->bfOffBits - 3;

Jump= 0;

for(iCntY = 0; iCntY < Bm.bmiHeader.biHeight ; ++iCntY)  

{        

for(iCntX = 0; iCntX  < Bm.bmiHeader.biWidth  ; ++iCntX, Jump += 3)

{

ucpPixel = ucpPixel + 3;

if(lpData->lpData[Jump + 2] > 100)

{

continue;

}

else if(lpData->lpData[Jump + 1] > 100)

{

continue;

}

else if(lpData->lpData[Jump + 0] > 50)

{

lpData->lpData[Jump] = *(ucpPixel + 0);  // Blue

lpData->lpData[Jump + 2] = *(ucpPixel + 2);  // Red

lpData->lpData[Jump + 1] = *(ucpPixel + 1);  // Green

}

}

ucpPixel = ucpPixel + uiPad;

}

// 영상 정보 편집 // 끝----------------------------------------------


// 편집된 영상 그리기 // 시작----------------------------

StretchDIBits(hdc  , Bm.bmiHeader.biWidth +20

, 0

, Bm.bmiHeader.biWidth

, Bm.bmiHeader.biHeight

, 0

, 0

, Bm.bmiHeader.biWidth

, Bm.bmiHeader.biHeight

, lpData->lpData

, &Bm

, DIB_RGB_COLORS

, SRCCOPY);

// 편집된 영상 그리기 // 끝------------------------------


ReleaseDC(HWndMain, hdc);


return 0;

}


이 부분을 수업하실 듯 하다.

어떤 특정 값 보다(ex > 100) 현재 데이터가 크다면 continue 하면서 데이터 값을 가져오지 않고 그대로




파란배경으로 만들고 올리는것 블루 스크린 개념이 도입된다.

블루가 가장 색을 빼기가 쉽기 때문이다.









#include <windows.h>
#include <Vfw.h>
//#pragma comment (lib, "vfw32.lib")

#define  X_SCALE    320
#define  Y_SCALE    240

#define  BACKGROUND_SIZE  (X_SCALE * Y_SCALE * 3)

#define  M_ALPHA      170 //미들
#define  G_ALPHA      30  //Gap

//프로그램 할 때 쓰이는 애ㅑ들
#define  H_ALPHA      (M_ALPHA + G_ALPHA)  //높이?
#define  L_ALPHA      (M_ALPHA - G_ALPHA)  //길이?

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPSTR lpszClass = L"VFW";

LRESULT On_Destroy(WPARAM wParam, LPARAM lParam);
LRESULT On_Create(WPARAM wParam, LPARAM lParam);
LRESULT On_Paint(WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK Capture(HWND hWnd, LPVIDEOHDR lpVHdr);

typedef  struct _stMsgMap
{
  UINT uiMsg;
  LRESULT(*fp)(WPARAM, LPARAM);
}StMsgMap;

StMsgMap msgMap[] =
{
  { WM_DESTROY, On_Destroy },
  { WM_CREATE, On_Create },
  { WM_PAINT, On_Paint },
  { WM_NULL, 0 }
};

HWND hWnd;

BITMAPINFO stBmpInfo;
static BYTE bData[BACKGROUND_SIZE];  //비트맵 파일 적재

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
  , LPSTR lpszCmdParam, int nCmdShow)
{
  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)WndProc;
  WndClass.lpszClassName = lpszClass;
  WndClass.lpszMenuName = NULL;
  WndClass.style = CS_HREDRAW | CS_VREDRAW;
  RegisterClass(&WndClass);

  hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
    NULL, (HMENU)NULL, hInstance, NULL);
  ShowWindow(hWnd, nCmdShow);

  while (GetMessage(&Message, 000)) 
  {
    TranslateMessage(&Message);
    DispatchMessage(&Message);
  }
  return Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWpWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
  StMsgMap *stpMap = msgMap;

  hWnd = hWpWnd;

  while ((*stpMap).uiMsg != WM_NULL)
  {
    if (iMessage == (*stpMap).uiMsg)
    {
      ((*stpMap).fp)(wParam, lParam);

      return 0;
    }

    ++stpMap;
  }

  return(DefWindowProc(hWpWnd, iMessage, wParam, lParam));
}

LRESULT On_Destroy(WPARAM wParam, LPARAM lParam)
{
  PostQuitMessage(0);

  return 0;
}

LRESULT On_Create(WPARAM wParam, LPARAM lParam)
{
  HWND hCamera;
  BOOL bRet;
  HANDLE hFile;  // 한번 읽고 닫기 때문에 static x
  DWORD dwCount;

  hFile = CreateFile(L"C:\\6666.bmp", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hFile == INVALID_HANDLE_VALUE)
  {
    MessageBox(hWnd, L"On_Create()의 CreateFile() 에러.", L"Button", MB_OK);
    PostQuitMessage(0);
    return 0;
  }

  bRet = ReadFile(hFile, bData, (BACKGROUND_SIZE), &dwCount, NULL);
  if (bRet == FALSE)
  {
    CloseHandle(hFile);
    MessageBox(hWnd, L"On_Create()의 ReadFile() 에러. - .bmp 파일 읽기 실패", L"Button", MB_OK);
    PostQuitMessage(0);
    return 0;
  }

  //1. 비디오캡처 윈도우를 지정된 영역에 원하는 크기로 생성
  hCamera = capCreateCaptureWindowW(L"Camera", WS_CHILD | WS_VISIBLE, 00, X_SCALE, Y_SCALE, hWnd, 0);
  if (hCamera == 0)
  {
    MessageBox(hWnd, "On_Create() 의 capCreateCaptureWindowW() 에러. 캡쳐 윈도우 생성 실패.""Button", MB_OK);
    PostQuitMessage(0);
  }
  //2. 캡처 윈도우와 드라이버 연결
  bRet = capDriverConnect(hCamera, 0);
  if (bRet == FALSE)
  {
    MessageBox(hWnd, "On_Create() 의 capDriverConnect() 에러. 드라이버에 연결할 수 없습니다.""Button", MB_OK);
    PostQuitMessage(0);
  }
  //3. 캡처윈도우에 프리뷰 모드로 찍을 프레임 값 설정
  capPreviewRate(hCamera, 1);    //숫자가 작을 수록 화면에 보이는 속도가 빨라진다.
  //4. 캡처되는 이미지의 정보를 얻어냄
  capGetVideoFormat(hCamera, &stBmpInfo, sizeof(stBmpInfo));
  //5. 원하는 크기로 생성시킨 값으로 수정
  stBmpInfo.bmiHeader.biWidth = X_SCALE;
  stBmpInfo.bmiHeader.biHeight = Y_SCALE;
  //6. 콜백 함수 호환을 위한 비디오 포맷 설정
  capSetVideoFormat(hCamera, &stBmpInfo, sizeof(stBmpInfo));
  //7. 콜백 함수 호출
  capSetCallbackOnFrame(hCamera, Capture);
  //8. 캡쳐 윈도우에 프리뷰 모드로 보여줌
  capPreview(hCamera, TRUE);

  CloseHandle(hFile);

  return 0;
}

LRESULT On_Paint(WPARAM wParam, LPARAM lParam)
{
  HDC hdc;
  PAINTSTRUCT ps;

  hdc = BeginPaint(hWnd, &ps);
  EndPaint(hWnd, &ps);

  return 0;
}

//그림한장 호출될때마다 이 함수가 호출. 2번째 인자에 비디오 정보가 실려오기에 헤더를 분석해야한다.
LRESULT CALLBACK Capture(HWND hWpWnd, LPVIDEOHDR lpVHdr)
{
  HDC hdc;
  int iCountX;
  int iCountY;
  int iCal;  //코드 줄이기 용 변수
  WCHAR wcStr[50= { 0, };
  static BYTE vData[X_SCALE * Y_SCALE * 3];  //영상처리를 위해서 데이터 값을 그대로 가져올 것.

  hdc = GetDC(hWnd);

  //memcpy(vData, lpVHdr->lpData, lpVHdr->dwBufferLength);
  for (iCountY = 0; iCountY < Y_SCALE; ++iCountY)
  {
    for (iCountX = 0; iCountX < X_SCALE; ++iCountX)
    {
      iCal = (iCountY * X_SCALE + iCountX) * 3;
      vData[iCal + 0= lpVHdr->lpData[iCal + 0];
      vData[iCal + 1= lpVHdr->lpData[iCal + 1];
      vData[iCal + 2= lpVHdr->lpData[iCal + 2];

      if (vData[iCal + 0> H_ALPHA)
      {
        continue;
      }
      if (vData[iCal + 0< L_ALPHA)
      {
        continue;
      }

      if (vData[iCal + 1> H_ALPHA)
      {
        continue;
      }
      if (vData[iCal + 1< L_ALPHA)
      {
        continue;
      }

      if (vData[iCal + 2> H_ALPHA)
      {
        continue;
      }
      if (vData[iCal + 2< L_ALPHA)
      {
        continue;
      }

      //칠판 비트맵 사진으로 교체 하기
      vData[iCal + 0= bData[iCal + 0];
      vData[iCal + 1= bData[iCal + 1];
      vData[iCal + 2= bData[iCal + 2];
    }
  }
  StretchDIBits(hdc, X_SCALE, 0, X_SCALE, Y_SCALE, 00, X_SCALE, Y_SCALE, vData, &stBmpInfo, DIB_RGB_COLORS, SRCCOPY);

  ReleaseDC(hWnd, hdc);

  return 0;
}






728x90