2010. 6. 21. 15:32ㆍ2010년/6월
#include<Windows.h>
#include"vfw.h"
#include <math.h>
#include <iostream>
#include "soullex.h"
#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 //크기설정
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;
LPCTSTR lpszClass = TEXT("VFW 기본 예제");
BYTE *imageData; //파일open한 이미지정보 받을 포인터
BITMAPFILEHEADER bmfh; // 파일open한 비트맵파일해더 정보
BITMAPINFO *binfo; //파일open한 비트맵인포정보
LONG width4; //폭설정값
// 변환할 정보
BITMAPINFO *chbinfo; //크기 변경된 비트맵인포정보
BYTE *chData; //크기 변경된 비트맵DATA값
BITMAPINFO *YIQbinfo;
BYTE *YIQData;
BITMAPINFO *Bbinfo;
BYTE *BData;
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,
300, 300, 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);
ReleaseDC(hWnd,Hdc);
return 0;
case WM_DESTROY:
if(chData!=NULL){
free(chData);
chData=NULL;
}
if(imageData!=NULL){
free(imageData);
imageData =NULL;
}
if(YIQData!=NULL){
free(YIQData);
imageData =NULL;
}
if(BData!=NULL){
free(BData);
BData =NULL;
}
free(binfo);
PostQuitMessage(0);
return 0;
}
return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}
LRESULT CALLBACK FramInfo(HWND hVFW, LPVIDEOHDR VideoHdr)
{
HDC Hdc;
HDC hMemDC; //메모리DC
HBITMAP OldBitmap;
// int i,j;
int height, width;
LONG chwidth,chheight;
int Y,I,Q;
//비트맵 영상 정보
//영상출력을 위한 변수
capPreviewRate(hVFW, 0); //프리뷰모드에서 보여질 프레임 속도를 0으로 설정함
chwidth = Bm.bmiHeader.biWidth *ZOOMSIZE;
chheight = Bm.bmiHeader.biHeight *ZOOMSIZE;
width4=chwidth*3;
width4=WIDTH4(width4);
//bitmapinfo의 size를 바꾸어서 받아온다.
chbinfo = ChangeBitmapInfo(chwidth,chheight,&Bm,24);
chData=(BYTE *)malloc(Bm.bmiHeader.biSizeImage);
YIQbinfo =ChangeBitmapInfo(chwidth,chheight,&Bm,8);
YIQData=(BYTE *)malloc(YIQbinfo->bmiHeader.biSizeImage);
Bbinfo =ChangeBitmapInfo(chwidth,chheight,&Bm,8);
BData=ReSizeImage(&Bm,chbinfo,VideoHdr->lpData,8);
// 즉 어떠한 처리가 다 끝나기 전에는 다시 콜백함수가 호출되게 하지 않는다
for(height=0;height<chheight;++height)
{
for(width=0;width<chwidth;++width)
{
Y=VideoHdr->lpData[height*width4+width*3];
I=VideoHdr->lpData[height*width4+width*3+1];
Q=VideoHdr->lpData[height*width4+width*3+2];
chData[height*width4+width*3]=(Y*0.299)+(I*0.587)+(Q*0.114);
chData[height*width4+width*3+1]=(Y*0.596)+(I*-0.275)+(Q*-0.321);
chData[height*width4+width*3+2]=(Y*0.212)+(I*-0.525)+(Q*0.311);
}
}
for(height=0;height<chheight;++height)
{
for(width=0;width<chwidth;++width)
{
Y=VideoHdr->lpData[height*width4+width*3];
I=VideoHdr->lpData[height*width4+width*3+1];
Q=VideoHdr->lpData[height*width4+width*3+2];
Y=(Y*0.299)+(I*0.587)+(Q*0.114);
YIQData[height*width4/3+width]=Y;
}
}
height = Bm.bmiHeader.biHeight; //캡쳐영상의 세로
width = Bm.bmiHeader.biWidth; //캡쳐영상의 가로
MoveWindow(hWndMain,200,200,width*2+40,height*2+40,TRUE);
Hdc=GetDC(Hwndmain);
hMemDC = CreateCompatibleDC(Hdc);
OldBitmap = (HBITMAP)SelectObject(hMemDC,hBit);
SetDIBitsToDevice(Hdc,0,0,width,height,NULL,NULL,NULL,height,VideoHdr->lpData,&Bm,DIB_RGB_COLORS);
SetDIBitsToDevice(Hdc,width+10,0,width,height,NULL,NULL,NULL,height,chData,chbinfo,DIB_RGB_COLORS);
SetDIBitsToDevice(Hdc,0,height+10,width,height,NULL,NULL,NULL,height,YIQData,YIQbinfo,DIB_RGB_COLORS);
SetDIBitsToDevice(Hdc,width+10,height+10,width,height,NULL,NULL,NULL,height,BData,Bbinfo,DIB_RGB_COLORS);
SelectObject(hMemDC, OldBitmap);
DeleteDC(hMemDC);
ReleaseDC(Hwndmain, Hdc);
capPreviewRate(hVFW,1); //다음 프레임에는 다시 영상처리를 시작 하게 된다.
return 0;
}
================================================================
================================================================
soullex.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;
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;
}
왼쪽위가 원본의 화면이고 YIQ의공식으로 바뀐화면이 오른쪽이며
왼쪽밑이 8비트로 변경한 Y만 놔두고 화면이며
오른쪽밑이 원본의 8비트 변경이다
사실 눈으로 약간 구별하기는 난 어렵다 -_-;;
=========================================================
============================================================================
기본적으로 우리가 사용하던 RGB는 빛의 3요소이다 그래서 빛의 밝기에따라 색상이 약간 바뀐다.
그래서 사람이 보는 것과 컴퓨터가 보는것은 틀리다 그래서 RGB에서 파생된것이 여러가지가
있는데 그중에서 YIQ HIS등 여러가지가 있다. 그중에서 오늘은 YIQ를 사용하는것이고 24비트는
힘드니깐 8비트로 처리하며 이과정은 어두운곳과 밝은부분을 좀더 더어둡고 더밝게 보여준다.
============================================================================
============================================================================
자바를 사용하기 위해서 여러가지 받아야하는 파일과 설정이 필요하다
JDK와 JRE의 차이점은 거진 실행용인지 프로그램용인지 때문에 JDK를 해야한다.
6은 현재 버전이고 6에서 update가 20번 된것이다.
그리고 eclipse를 깔아야한다.
깔면된다. 그리고 자바는 실행하면되고
이클립스는 받은파일을 압축을 풀어서 C에다가 풀면된다.
바탕화면에 풀면 되고
그림으로 간단하게 설명해보자
New Java Project를 눌려서 새로 만들수가 있고
New 의 클래스를 새로 생성한다.
public static void main부분에 체크하고 실행하면된다.
왼쪽처럼 만들고 본문에 System.out.println("Hello Wrold");를 통해서 출력이 된다.
Java는 기존의 C와의 약간의 차이점이 있다 클래스도 있지만 자료형도 약간 있다.
char가 2바이트로 전세계의 모든언어를 만들기위해서 2바이트를 했고 long이 8바이트라는것과
byte가 1바이트라는걸 알아두면된다.
'2010년 > 6월' 카테고리의 다른 글
6월24일 자바(클래스) 영상처리(프로젝트) (0) | 2010.06.24 |
---|---|
6월23일 영상처리(프로젝트시작 ) RFID(Scanner) (0) | 2010.06.23 |
6월17일 영상처리(히스토그램,2진화 (0) | 2010.06.17 |
6월16일 영상처리(흑백크기) (0) | 2010.06.16 |
6월15일 영상처리(흑백 크기축소확대) (0) | 2010.06.16 |