C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[49284] Re:Re:Re:Re:비트맵 파일 외각선 추출 관련 - scanline으로 하면 빨라요
장성호 [nasilso] 1684 읽음    2007-05-17 11:28
짱님의 샘플에 흑백으로 된 이미지에 외각선을 찾는데 문제는 없습니다.

그런데 Canvas->Pixels[][]로 접근하면 속도가 많이 느려요

대신 ScanLine으로 하면 빠르죠

짱님의 샘플을 그대로 ScanLine으로 바꿔봤습니다.
코드가 길지만 짱님의 코드한 원리그대로
어떤 Pixel의 상하좌우에 검은색이 있으면 그 Pixel을 Red로 바꾼것입니다.

잉... 쓰다가 보니까 조금 다르네요
짱님은 대각선까지 비교했는데
저는 대각선을 비교하진 않아네요. (쩝쩝)

하여간 GetTickCount로 속도를 체크해보면 10배이상 차이납니다.
코드가 얼른 눈에 안 들어올수 있겠지만   ....
속도도 중요하니깐....

그럼


// Canvas->Pixels[][] 로 접근해서..
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{

    long int tic=GetTickCount();
    int ImageWidth  = Image1->Width;
    int ImageHeight = Image1->Height;
    for(int x=0; x<ImageWidth; x++)
    {
        for(int y=0; y<ImageHeight; y++)
        {
            if(Image1->Canvas->Pixels[x][y] == clWhite)
            {
                if(Image1->Canvas->Pixels[x-1][y-1]==clBlack ||
                   Image1->Canvas->Pixels[x-1][y  ]==clBlack ||
                   Image1->Canvas->Pixels[x-1][y+1]==clBlack ||
                   Image1->Canvas->Pixels[x  ][y-1]==clBlack ||
                   Image1->Canvas->Pixels[x  ][y+1]==clBlack ||
                   Image1->Canvas->Pixels[x+1][y-1]==clBlack ||
                   Image1->Canvas->Pixels[x+1][y  ]==clBlack ||
                   Image1->Canvas->Pixels[x+1][y+1]==clBlack   )
                   Image1->Canvas->Pixels[x  ][y  ]=clRed;

            }

        }
    }
    Label1->Caption=IntToStr(GetTickCount()-tic);

}
//---------------------------------------------------------------------------

// ScanLine으로  접근해서..
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    long int tic=GetTickCount();
    int ImageWidth  = Image1->Width;
    int ImageHeight = Image1->Height;

    RGBTRIPLE *pt1,*pt2,*ptu,*ptd;
    ptu=NULL;
    ptd=NULL;
    for(int h=0; h<ImageHeight; h++)
    {
        pt1=(RGBTRIPLE *)Image1->Picture->Bitmap->ScanLine[h];
        if(h>0)
        {
            ptu=(RGBTRIPLE *)Image1->Picture->Bitmap->ScanLine[h-1];
        }
        if(h<(ImageHeight-1))
        {
            ptd=(RGBTRIPLE *)Image1->Picture->Bitmap->ScanLine[h+1];
        }
        else ptd=NULL;

        for(int w=0; w<ImageWidth; w++)
        {
            if(pt1->rgbtBlue==255 && pt1->rgbtGreen==255 && pt1->rgbtRed==255)
            {

                if(ptu && ptu->rgbtBlue==0 && ptu->rgbtGreen==0 && ptu->rgbtRed==0)
                {
                    pt1->rgbtRed=255;
                    pt1->rgbtBlue=0;
                    pt1->rgbtGreen=0;
                }
                else if(ptd && ptd->rgbtBlue==0 && ptd->rgbtGreen==0 && ptd->rgbtRed==0)
                {
                    pt1->rgbtRed=255;
                    pt1->rgbtBlue=0;
                    pt1->rgbtGreen=0;
                }
                else
                {

                    if(w>0)
                    {
                        pt2=pt1;
                        pt2--;

                        if(pt2->rgbtBlue==0 && pt2->rgbtGreen==0 && pt2->rgbtRed==0)
                        {
                            pt1->rgbtRed=255;
                            pt1->rgbtBlue=0;
                            pt1->rgbtGreen=0;
                        }
                    }

                    if(w<(ImageWidth-1))
                    {
                        pt2=pt1;
                        pt2++;

                        if(pt2->rgbtBlue==0 && pt2->rgbtGreen==0 && pt2->rgbtRed==0)
                        {
                            pt1->rgbtRed=255;
                            pt1->rgbtBlue=0;
                            pt1->rgbtGreen=0;
                        }
                    }
                }
            }
            pt1++;
            if(ptu)ptu++;
            if(ptd)ptd++;

        }
    }
    Image1->Repaint();
    Label2->Caption=IntToStr(GetTickCount()-tic);
}
//---------------------------------------------------------------------------



짱 님이 쓰신 글 :
: 원이 되믄 다 될듯해서 원으로 된거 올립니다.
:
: 혹시 안되믄 회신 주세요
:
: 즐거운 하루 되시길....
:
:
:
: 정구일 님이 쓰신 글 :
: : 먼저 답변 감사드립니다.
: :
: : 이렇게 많은 분들이 도와주실줄 몰랐는데^^*
: :
: : 제가 원하는 바를 너무 잘 아시는거 같아요.
: :
: : 저도 처음에는 이미지 로딩 시켜서 8 방향으로 색을 검출 하려고 했습니다.
: :
: : 그런데 실력이 안되다 보니... 다른쪽으로 생각 해본게 위에 보신거에요^^;
: :
: : 혹시 실례가 안된다면 샘플 프로그램 가능할까요^^?
: :
: : 짱 님이 쓰신 글 :
: : : 안녕하세요...
: : :
: : : 님의 프로그램을 실행해 보지 않아서 정확히 알 수는 없으나,
: : :
: : : 제가 봐서는 현재 배경이 빨강, 녹색, 파랑 색일 경우에도 하얀 색으로 될듯 합니다.
: : :
: : : 그리고 경계구하는 부분에서 정사각형을 그려서 Test하면 왼쪽면 왼쪽 라인만 검출 될듯 하구요...
: : :
: : : 자....일단 영상 Test하는 방법부터 바꾸심이 어떠하실지.
: : :
: : : 폼하나 만들고 이미지 하나 만들고 이미지 로딩하는 버튼 하나 만들어서
: : :
: : : BMP 파일을 불러서 이미지에 넣어서 Test 하시는 것이 좋습니다.
: : :
: : : 자...이제 링을 상상해 봤을 때 모든 edge를 다 검출 할지 아니면 링의 외곽만 검출 할지를 먼저 결정합니다.
: : :
: : : 프로그램 상으로는 모든걸 검출 하는게 쉽죠....
: : :
: : : 모든걸 검출 할때는 for문으로 영상의 폭, 높이 만큼 돌리고 현재 픽셀이 clWhite 면 4방 검사 ( 상하좌우 ), 할지
: : :
: : : 8방(인접 8방향 )에 대해 검출 할지를 결정 하고,
: : :
: : : 4방이면 상하좌우 중 검은색이 있는지 검사 합니다.
: : :
: : : 만약 외곽만 하고 싶다면 for문으로 각 방향에서 반대 방향으로 검사를 진행 하고 edge가 보이면 라인을
: : : 
: : : 넘어 가는 형태로 짜시믄 외곽만 되죠...물론 원을 찾는데도 문제 없고
: : :
: : : 아....결과를 바로 원영상에 뿌리지 말고 같은 Image를 하나 만들어서 결과 이미를 따로 display 하세요...
: : :
: : : 나중에 좀 아실거 같을때 포인터로 처리 하시고 영상도 scanline 쓰시면 속도에 문제 없을듯.
: : :
: : : 다른 분이 지적한거 처럼 노이즈가 문제가 될경우에는 일단 생각하지 마세요....
: : :
: : : 그거 보다 많은 문제들이 있을테니 해결 하고 나면 노이즈는 없어져요....
: : :
: : : 예를 들면 edge 길이 구할려고 하면하는데 중간에 끊어졌다거나 gray가 서로 다르게 차이 난다거나...하시면서 느끼시길...
: : :
: : : 하다가 안되믄 회신 주세요....sample program 하나 짜 드리죠...
: : :
: : :
: : :
: : : 정구일 님이 쓰신 글 :
: : : : 안녕하세요.
: : : : 비트맵 파일 외각선 추출에 관해서 질문이 있어서 이렇게 질문드립니다.
: : : : 비트맵 파일을 불러와서 외각선을 추출해야 합니다.
: : : : 그래서 bmp 파일 rgb 값을 사용하여 외각선을 추출하려고 합니다.
: : : : 방법은 우선 배경은 하얀색이라는 가정을 두고 시작했습니다.
: : : : 배경이 하얀색이기 때문에 하얀색 이외의 색은 모두 검은색으로 만듭니다.
: : : : 그리고 rgb 값을 읽어 하얀색 rgb 값 다음 rgb 값이 검은색이면
: : : : 그 곳이 경계선이 되게 했습니다.
: : : : 그런데 약간의 문제가 있는지 생각 처럼 잘 되지 않습니다.
: : : : 무엇이 잘 못 되었는지 봐주시면 감사하겠습니다.
: : : :
: : : : /*
: : : :     비트맵 파일 이미지를 불러와서 그 이미지에 외각선을 추출한다.
: : : :     그 이미지에 배경색은 하얀색이다.
: : : : */
: : : :
: : : : #include <stdio.h>
: : : :
: : : : #define BYTE unsigned char
: : : : #define MAX 1000                // 비트맵에 크기를 자동으로 계산 하는 방법을 모르겠습니다.
: : : :
: : : : struct BMP_DATA                    // 비트맵 RGB값
: : : : {
: : : :     BYTE    r;
: : : :     BYTE    g;
: : : :     BYTE    b;
: : : : };
: : : :
: : : : void main()
: : : : {
: : : :     static struct BMP_DATA rgb[MAX];
: : : :     int i = 0;
: : : :     FILE *fp;
: : : :     fp = fopen ("test.bmp", "w");
: : : :
: : : :     while (i < MAX)                // 비트맵 배경이 하얀색이지만 완전 하얀색이 아닐수 있으므로 완전 하얀색을 만든다.
: : : :     {
: : : :         if (rgb[i].r > 220)
: : : :         {
: : : :             rgb[i].r = 255;
: : : :         }
: : : :         if (rgb[i].g > 220)
: : : :         {
: : : :             rgb[i].g = 255;
: : : :         }
: : : :         if (rgb[i].b > 220)
: : : :         {
: : : :             rgb[i].b = 255;
: : : :         }
: : : :         i++;
: : : :     }
: : : :
: : : :     while (i < MAX)                // 배경이 아니라면 검은색으로 바꾼다.
: : : :     {
: : : :         if (rgb[i].r != 255)
: : : :         {
: : : :             rgb[i].r = 0;
: : : :         }
: : : :         if (rgb[i].g != 255)
: : : :         {
: : : :             rgb[i].g = 0;
: : : :         }
: : : :         if (rgb[i].b != 255)
: : : :         {
: : : :             rgb[i].b = 0;
: : : :         }
: : : :         i++;
: : : :     }
: : : :
: : : :     while (i < MAX)                // 하얀색 다음 검은색이라면 그 곳이 경계 이므로 색을 바꾼다.
: : : :     {
: : : :         if (rgb[i].r == 255 || rgb[i].g == 255 || rgb[i].b == 255)
: : : :         {
: : : :             if (rgb[i+1].r == 0 || rgb[i+1].g == 0 || rgb[i+1].b == 0)
: : : :             {
: : : :                 rgb[i].r = 100;
: : : :                 rgb[i].g = 100;
: : : :                 rgb[i].b = 100;
: : : :             }
: : : :         }
: : : :         i++;
: : : :     }
: : : :     fclose(fp);
: : : : }

+ -

관련 글 리스트
49245 비트맵 파일 외각선 추출 관련 정구일 1867 2007/05/14
49271     Re:비트맵 파일 외각선 추출 관련 2456 2007/05/16
49278         Re:Re:비트맵 파일 외각선 추출 관련 정구일 1593 2007/05/16
49283             Re:Re:Re:비트맵 파일 외각선 추출 관련 1456 2007/05/17
49290                 Re:Re:Re:Re:비트맵 파일 외각선 추출 관련 정구일 1423 2007/05/17
49293                     Re:Re:Re:Re:Re:비트맵 파일 외각선 추출 관련 1292 2007/05/17
49299                         Re:Re:Re:Re:Re:Re:비트맵 파일 외각선 추출 관련 정구일 1295 2007/05/17
49301                             Re:Re:Re:Re:Re:Re:Re:비트맵 파일 외각선 추출 관련 1374 2007/05/18
49302                                 Re:Re:Re:Re:Re:Re:Re:Re:비트맵 파일 외각선 추출 관련 정구일 1405 2007/05/18
49300                             Re:Re:Re:Re:Re:Re:Re:비트맵 파일 외각선 추출 관련 1311 2007/05/18
49284                 Re:Re:Re:Re:비트맵 파일 외각선 추출 관련 - scanline으로 하면 빨라요 장성호 1684 2007/05/17
49261     Re:비트맵 파일 외각선 추출 관련 장성호 2257 2007/05/14
49270         Re:Re:비트맵 파일 외각선 추출 관련 정구일 1453 2007/05/15
49257     Re:비트맵 파일 외각선 추출 관련 머슴.한석복 2109 2007/05/14
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.