|
짱님의 샘플에 흑백으로 된 이미지에 외각선을 찾는데 문제는 없습니다.
그런데 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);
: : : : }
|