求图形处理的资料(50分)

  • 主题发起人 主题发起人 lczhuohuo
  • 开始时间 开始时间
L

lczhuohuo

Unregistered / Unconfirmed
GUEST, unregistred user!
谁有关于图像边缘化的资料啊??有算法当然好了
 
你指边缘检测吧。
对图象进行卷积
-1 -1 -1
-1 8 -1
-1 -1 -1
即可。
 
什么意思?

 
大致是用一些因子,例如拉普拉斯,傅立叶,进行矩阵变化
《计算机学报》或者《中国图形图像学报》上有相关的文章
 
这还不是我满意的答案,请继续。
 
忘了从哪里down的:
边沿检测与提取,轮廓跟踪
命令行编译过程如下
vcvars32
rc bmp.rc
cl edge.c bmp.res user32.lib gdi32.lib
注意事项:
运行时,文件c:/test.bmp必须存在

//////////////////////////////////////////////////////////////
//Name:edge.c
//Purpose: edge detectiong and hough transform
//Author: phoenix, CS, TshingHua, Beijing, P.R.C.
//Email: bjlufengjun@www.163.net or lufengjun@hotmail.com
//Date:April 3, 1998

//header file
#include "bmp.h"
#include "memory.h"
#include "math.h"
#include "stdio.h"
//owner defined stack
typedef struct{
HGLOBAL hMem;
POINT *lpMyStack;
LONG ElementsNum;
LONG ptr;
}MYSTACK;
//macro definition
#define WIDTHBYTES(i) ((i+31)/32*4)
#define PI 3.1415926535

//function declaration
int PASCAL WinMain (HANDLE, HANDLE, LPSTR, int);
LRESULT CALLBACK MainWndProc(HWND , UINT,WPARAM, LPARAM);
BOOL LoadBmpFile (HWND hWnd,char *BmpFileName);
BOOL TemplateOperation(HWND hWnd, int TemplateType);
BOOL Outline(HWND hWnd);
BOOL Hough(HWND hWnd);
BOOL LapOfGauss(HWND hWnd);
BOOL Contour(HWND hWnd);
BOOL IsContourP(LONG x,LONG y, char *lpPtr);
BOOL SeedFill(HWND hWnd);
BOOL InitStack(HWND hWnd,LONG StackLen);
void DeInitStack();
BOOL MyPush(POINT p);
POINT MyPop();
BOOL IsStackEmpty();
//global variable declaration
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
HPALETTE hPalette=NULL;
HBITMAP hBitmap=NULL;
HGLOBAL hImgData=NULL;
DWORD NumColors;
DWORD LineBytes;
HINSTANCE ghInst;
DWORD ImgWidth=0 , ImgHeight=0;
//template array
float Template_Smooth_Box[9]={1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f};
float Template_Smooth_Gauss[9]={1.0f,2.0f,1.0f,2.0f,4.0f,2.0f,1.0f,2.0f,1.0f};
float Template_Sharpen_Laplacian[9]={-1.0f,-1.0f,-1.0f,-1.0f,9.0f,-1.0f,-1.0f,-1.0f,-1.0f};
float Template_HSobel[9]={-1.0f,0.0f,1.0f,-2.0f,0.0f,2.0f,-1.0f,0.0f,1.0f};
float Template_VSobel[9]={-1.0f,-2.0f,-1.0f,0.0f,0.0f,0.0f,1.0f,2.0f,1.0f};
float Template_HIsoSobel[9]={-1.0f,0.0f,1.0f,-1.4142f,0.0f,1.4142f,-1.0f,0.0f,1.0f};
float Template_VIsoSobel[9]={-1.0f,-1.4142f,-1.0f,0.0f,0.0f,0.0f,1.0f,1.4142f,1.0f};
float Template_Log[25]={-2.0f,-4.0f,-4.0f,-4.0f,-2.0f,
-4.0f,0.0f,8.0f,0.0f,-4.0f,
-4.0f,8.0f,24.0f,8.0f,-4.0f,
-4.0f,0.0f,8.0f,0.0f,-4.0f,
-2.0f,-4.0f,-4.0f,-4.0f,-2.0f};
MYSTACK SeedFillStack;
POINT SeedPoint;
BOOL IsSelecting;
///////////////////////////////////////////////////////////
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS wndclass;
HWND hWnd;

ghInst=hInstance;
if ( ! hPrevInstance ){
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = MainWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH);
wndclass.lpszMenuName = "BMPMENU";
wndclass.lpszClassName = "phoenix ip system";
}

if ( ! RegisterClass (&wndclass) )
return FALSE;

hWnd = CreateWindow ("phoenix ip system","Edge detectiong and hough transform",
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL,NULL,
hInstance, NULL);
if (!hWnd)
return FALSE;
ShowWindow (hWnd, SW_SHOWMAXIMIZED);
UpdateWindow (hWnd);

while ( GetMessage (&msg, NULL, 0, 0) ){
TranslateMessage (&msg);
DispatchMessage (&msg);
}

IsSelecting=FALSE;
return msg.wParam;
}
////////////////////////////////////////////////////////////////
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message,WPARAM wParam, LPARAM lParam)
{
static HDC hDC,hMemDC;
PAINTSTRUCT ps;

switch (message){
case WM_PAINT:
{
hDC = BeginPaint(hWnd, &ps);
if (hBitmap)
{
hMemDC = CreateCompatibleDC(hDC);
if (hPalette)
{
SelectPalette (hDC, hPalette, FALSE);
SelectPalette (hMemDC, hPalette, FALSE);
RealizePalette (hDC);
}
SelectObject(hMemDC, hBitmap);
BitBlt(hDC, 0, 0, ImgWidth,ImgHeight, hMemDC, 0, 0, SRCCOPY);
DeleteDC(hMemDC);
}
EndPaint(hWnd, &ps);
break;
}
case WM_DESTROY: //注意释放内存和位图,调色板句柄
if(hBitmap!=NULL)
DeleteObject(hBitmap);

if(hPalette!=NULL)
DeleteObject(hPalette);

if(hImgData!=NULL){
GlobalUnlock(hImgData);
GlobalFree(hImgData);
}
PostQuitMessage (0);
return 0;
case WM_LBUTTONDOWN:
if(IsSelecting){
SeedPoint.x = LOWORD(lParam);
SeedPoint.y = HIWORD(lParam);
IsSelecting=FALSE;
if(SeedFill(hWnd))
InvalidateRect(hWnd,NULL,TRUE);
}
break;
case WM_COMMAND:
switch (wParam){
case IDM_LOADBMP:
//注意重新分配内存和调色板,位图句柄时,先释放原来的
if(hBitmap!=NULL){
DeleteObject(hBitmap);
hBitmap=NULL;
}
if(hPalette!=NULL){
DeleteObject(hPalette);
hPalette=NULL;
}
if(hImgData!=NULL){
GlobalUnlock(hImgData);
GlobalFree(hImgData);
hImgData=NULL;
}
if(LoadBmpFile(hWnd,"c://test.bmp")) //成功,则重画窗口
InvalidateRect(hWnd,NULL,TRUE);
break;
case IDM_OUTLINE:
if(hImgData!=NULL){
if(Outline(hWnd))
InvalidateRect(hWnd,NULL,TRUE);
}
else
MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION);
break;
case IDM_HSOBEL:
if(hImgData!=NULL){
if(TemplateOperation(hWnd,TEMPLATE_SOBEL_H))
InvalidateRect(hWnd,NULL,TRUE);
}
else
MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION);
break;
case IDM_VSOBEL:
if(hImgData!=NULL){
if(TemplateOperation(hWnd,TEMPLATE_SOBEL_V))
InvalidateRect(hWnd,NULL,TRUE);
}
else
MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION);
break;
case IDM_HISOSOBEL:
if(hImgData!=NULL){
if(TemplateOperation(hWnd,TEMPLATE_ISOSOBEL_H))
InvalidateRect(hWnd,NULL,TRUE);
}
else
MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION);
break;
case IDM_VISOSOBEL:
if(hImgData!=NULL){
if(TemplateOperation(hWnd,TEMPLATE_ISOSOBEL_V))
InvalidateRect(hWnd,NULL,TRUE);
}
else
MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION);
break;
case IDM_HOUGH:
if(hImgData!=NULL)
Hough(hWnd);
else
MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION);
break;
case IDM_LOG:
if(hImgData!=NULL){
if(LapOfGauss(hWnd))
InvalidateRect(hWnd,NULL,TRUE);
}
else
MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION);
break;
case IDM_CONTOUR:
if(hImgData!=NULL){
if(Contour(hWnd))
InvalidateRect(hWnd,NULL,TRUE);
}
else
MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION);
break;
case IDM_SEEDFILL:
if(hImgData!=NULL){
IsSelecting=TRUE;
MessageBox(hWnd,"Please click the area to be filled!","Message",MB_OK|MB_ICONEXCLAMATION);
}
else
MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION);
break;
case IDM_EXIT:
SendMessage(hWnd,WM_DESTROY,0,0L);
break;
}
break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
////////////////////////////////////////////////////////////////
BOOL LoadBmpFile (HWND hWnd,char *BmpFileName)
{
HFILE hf;
LPBITMAPINFOHEADER lpImgData;
LOGPALETTE *pPal;
LPRGBQUAD lpRGB;
HPALETTE hPrevPalette;
HDC hDc;
HLOCAL hPal;
DWORD ImgSize;
DWORD i;

if((hf=_lopen(BmpFileName,OF_READ))==HFILE_ERROR){
MessageBox(hWnd,"File c://test.bmp not found!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
_lread(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER));
_lread(hf,(LPSTR)&bi,sizeof(BITMAPINFOHEADER));
ImgWidth=bi.biWidth;
ImgHeight=bi.biHeight;
LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount);
ImgSize=(DWORD)LineBytes*bi.biHeight;
if(bi.biClrUsed!=0)
NumColors=(DWORD)bi.biClrUsed;
else
switch(bi.biBitCount){
case 1:
NumColors=2;
break;
case 4:
NumColors=16;
break;
case 8:
NumColors=256;
break;
case 24:
NumColors=0;
break;
default:
MessageBox(hWnd,"Invalid color numbers!","Error Message",MB_OK|MB_ICONEXCLAMATION);
_lclose(hf);
return FALSE;
}
if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)
+sizeof(BITMAPINFOHEADER)))
{
MessageBox(hWnd,"Invalid color numbers!","Error Message" ,MB_OK|
MB_ICONEXCLAMATION);
_lclose(hf);
return FALSE;
}
bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize;
if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPINFOHEADER)+
NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL)
{
MessageBox(hWnd,"Error alloc memory!","ErrorMessage",MB_OK|
MB_ICONEXCLAMATION);
_lclose(hf);
return FALSE;
}

lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
_llseek(hf,sizeof(BITMAPFILEHEADER),FILE_BEGIN);
_hread(hf,(char *)lpImgData,(long)sizeof(BITMAPINFOHEADER)
+(long)NumColors*sizeof(RGBQUAD)+ImgSize);
_lclose(hf);
if(NumColors!=0)
{
hPal=LocalAlloc(LHND,sizeof(LOGPALETTE) + NumColors* sizeof(PALETTEENTRY));
pPal =(LOGPALETTE *)LocalLock(hPal);
pPal->palNumEntries =(WORD) NumColors;
pPal->palVersion = 0x300;
lpRGB = (LPRGBQUAD)((LPSTR)lpImgData + (DWORD)sizeof(BITMAPINFOHEADER));
for (i = 0; i < NumColors; i++) {
pPal->palPalEntry.peRed=lpRGB->rgbRed;
pPal->palPalEntry.peGreen=lpRGB->rgbGreen;
pPal->palPalEntry.peBlue=lpRGB->rgbBlue;
pPal->palPalEntry.peFlags=(BYTE)0;
lpRGB++;
}
hPalette=CreatePalette(pPal);
LocalUnlock(hPal);
LocalFree(hPal);
}
hDc=GetDC(hWnd);
if(hPalette){
hPrevPalette=SelectPalette(hDc,hPalette,FALSE);
RealizePalette(hDc);
}
hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpImgData, (LONG)CBM_INIT,
(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER) +NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);
if(hPalette &amp;&amp; hPrevPalette){
SelectPalette(hDc,hPrevPalette,FALSE);
RealizePalette(hDc);
}

ReleaseDC(hWnd,hDc);
GlobalUnlock(hImgData);
return TRUE;
}
////////////////////////////////////////////////////////////////
BOOL TemplateOperation(HWND hWnd, int TemplateType)
{
DWORD OffBits,BufSize;
LPBITMAPINFOHEADER lpImgData;
LPSTR lpPtr;
HLOCAL hTempImgData;
LPBITMAPINFOHEADER lpTempImgData;
LPSTR lpTempPtr;
HDC hDc;
HFILE hf;
LONG x,y;
float coef;
float CoefArray[9];
float TempNum;
char filename[80];

switch(TemplateType){
case TEMPLATE_SMOOTH_BOX:
coef=(float)(1.0/9.0);
memcpy(CoefArray,Template_Smooth_Box,9*sizeof(float));
strcpy(filename,"c://smbox.bmp");
break;
case TEMPLATE_SMOOTH_GAUSS:
coef=(float)(1.0/16.0);
memcpy(CoefArray,Template_Smooth_Gauss,9*sizeof(float));
strcpy(filename,"c://smgauss.bmp");
break;
case TEMPLATE_SHARPEN_LAPLACIAN:
coef=(float)1.0;
memcpy(CoefArray,Template_Sharpen_Laplacian,9*sizeof(float));
strcpy(filename,"c://shlaplac.bmp");
break;
case TEMPLATE_SOBEL_H:
coef=(float)1.0;
memcpy(CoefArray,Template_HSobel,9*sizeof(float));
strcpy(filename,"c://hsobel.bmp");
break;
case TEMPLATE_SOBEL_V:
coef=(float)1.0;
memcpy(CoefArray,Template_VSobel,9*sizeof(float));
strcpy(filename,"c://vsobel.bmp");
break;
case TEMPLATE_ISOSOBEL_H:
coef=(float)1.0;
memcpy(CoefArray,Template_HIsoSobel,9*sizeof(float));
strcpy(filename,"c://hisobel.bmp");
break;
case TEMPLATE_ISOSOBEL_V:
coef=(float)1.0;
memcpy(CoefArray,Template_VIsoSobel,9*sizeof(float));
strcpy(filename,"c://visobel.bmp");
break;
}

OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);
BufSize=bf.bfSize-sizeof(BITMAPFILEHEADER);

if((hTempImgData=LocalAlloc(LHND,BufSize))==NULL)
{
MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);

lpPtr=(char *)lpImgData;
lpTempPtr=(char *)lpTempImgData;

memcpy(lpTempPtr,lpPtr,BufSize);

for(y=1;y<bi.biHeight-1;y++)
for(x=1;x<bi.biWidth-1;x++){
lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes)+x;
lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-y*LineBytes)+x;
TempNum=(float)((unsigned char)*(lpPtr+LineBytes-1))*CoefArray[0];
TempNum+=(float)((unsigned char)*(lpPtr+LineBytes))*CoefArray[1];
TempNum+=(float)((unsigned char)*(lpPtr+LineBytes+1))*CoefArray[2];
TempNum+=(float)((unsigned char)*(lpPtr-1))*CoefArray[3];
TempNum+=(float)((unsigned char)*lpPtr)*CoefArray[4];
TempNum+=(float)((unsigned char)*(lpPtr+1))*CoefArray[5];
TempNum+=(float)((unsigned char)*(lpPtr-LineBytes-1))*CoefArray[6];
TempNum+=(float)((unsigned char)*(lpPtr-LineBytes))*CoefArray[7];
TempNum+=(float)((unsigned char)*(lpPtr-LineBytes+1))*CoefArray[8];
TempNum*=coef;
if(TempNum>255.0) *lpTempPtr=(BYTE)255;
else if(TempNum<0.0)
*lpTempPtr=(unsigned char)fabs(TempNum);
else *lpTempPtr=(BYTE)TempNum;
}

hDc=GetDC(hWnd);
if(hBitmap!=NULL)
DeleteObject(hBitmap);

hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpTempImgData, (LONG)CBM_INIT,
(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER) +NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS);

hf=_lcreat(filename,0);
_lwrite(hf,(LPSTR)&amp;bf,sizeof(BITMAPFILEHEADER));
_lwrite(hf,(LPSTR)lpTempImgData,BufSize);
_lclose(hf);

ReleaseDC(hWnd,hDc);
LocalUnlock(hTempImgData);
LocalFree(hTempImgData);
GlobalUnlock(hImgData);
return TRUE;
}
////////////////////////////////////////////////////////////////
BOOL Outline(HWND hWnd)
{
DWORD BufSize;
LPBITMAPINFOHEADER lpImgData;
LPSTR lpPtr;
HLOCAL hTempImgData;
LPBITMAPINFOHEADER lpTempImgData;
LPSTR lpTempPtr;
HDC hDc;
HFILE hf;
LONG x,y;
int num;
int nw,n,ne,w,e,sw,s,se;

if( NumColors!=256){
MessageBox(hWnd,"Must be a mono bitmap with grayscale palette!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
BufSize=bf.bfSize-sizeof(BITMAPFILEHEADER);
if((hTempImgData=LocalAlloc(LHND,BufSize))==NULL)
{
MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);
//copy image data
memcpy(lpTempImgData,lpImgData,BufSize);

for (y=1;y<bi.biHeight-1;y++){
lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes);
lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-y*LineBytes);
for (x=1;x<bi.biWidth-1;x++){
if(*(lpPtr+x)==0){
nw=(unsigned char)*(lpPtr+x+LineBytes-1);
n=(unsigned char)*(lpPtr+x+LineBytes);
ne=(unsigned char)*(lpPtr+x+LineBytes+1);
w=(unsigned char)*(lpPtr+x-1);
e=(unsigned char)*(lpPtr+x+1);
sw=(unsigned char)*(lpPtr+x-LineBytes-1);
s=(unsigned char)*(lpPtr+x-LineBytes);
se=(unsigned char)*(lpPtr+x-LineBytes+1);
num=nw+n+ne+w+e+sw+s+se;
if(num==0)
*(lpTempPtr+x)=(unsigned char)255;
}
}
}

if(hBitmap!=NULL)
DeleteObject(hBitmap);
hDc=GetDC(hWnd);
hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpTempImgData, (LONG)CBM_INIT,
(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER) +NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS);

hf=_lcreat("c://outline.bmp",0);
_lwrite(hf,(LPSTR)&amp;bf,sizeof(BITMAPFILEHEADER));
_lwrite(hf,(LPSTR)lpTempImgData,BufSize);
_lclose(hf);

ReleaseDC(hWnd,hDc);
LocalUnlock(hTempImgData);
LocalFree(hTempImgData);
GlobalUnlock(hImgData);
return TRUE;
}
////////////////////////////////////////////////////////////////
BOOL Hough(HWND hWnd)
{
typedef struct{
int topx;
int topy;
int botx;
int boty;
}MYLINE;

DWORD BufSize;
LPBITMAPINFOHEADER lpImgData;
LPSTR lpPtr;
HDC hDc;
LONG x,y;
long i,maxd;
int k;
int Dist,Alpha;
HGLOBAL hDistAlpha,hMyLine;
int *lpDistAlpha;
MYLINE *lpMyLine,*TempLine,MaxdLine;
static LOGPEN rlp={PS_SOLID,1,1,RGB(255,0,0)};
HPEN rhp;

if( NumColors!=256){
MessageBox(hWnd,"Must be a mono bitmap with grayscale palette!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
Dist=(int)(sqrt( (double)bi.biWidth*bi.biWidth+(double)bi.biHeight*bi.biHeight)+0.5);
Alpha=180 /2 ; //0 degree to 178 degree , step is 2 degrees

if((hDistAlpha=GlobalAlloc(GHND,(DWORD)Dist* Alpha * sizeof(int)))==NULL){
MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

if((hMyLine=GlobalAlloc(GHND,(DWORD)Dist*Alpha*sizeof(MYLINE)))==NULL){
GlobalFree(hDistAlpha);
return FALSE;
}

BufSize=bf.bfSize-sizeof(BITMAPFILEHEADER);
lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
lpDistAlpha=(int *)GlobalLock(hDistAlpha);
lpMyLine=(MYLINE *)GlobalLock(hMyLine);

for (i=0;i<(long)Dist*Alpha;i++){
TempLine=(MYLINE*)(lpMyLine+i);
(*TempLine).boty=32767;
}

for (y=0;y<bi.biHeight;y++){
lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes);
for (x=0;x<bi.biWidth;x++)
if(*(lpPtr++)==0)
for (k=0;k<180;k+=2){
i=(long)fabs((x*cos(k*PI/180.0)+y*sin(k*PI/180.0)));
*(lpDistAlpha+i*Alpha+k/2)=*(lpDistAlpha+i*Alpha+k/2)+1;
TempLine=(MYLINE*)(lpMyLine+i*Alpha+k/2);
if(y> (*TempLine).topy){
(*TempLine).topx=x;
(*TempLine).topy=y;
}
if(y< (*TempLine).boty){
(*TempLine).botx=x;
(*TempLine).boty=y;
}
}
}

maxd=0;
for (i=0;i<(long)Dist*Alpha;i++){
TempLine=(MYLINE*)(lpMyLine+i);
k=*(lpDistAlpha+i);
if( k > maxd){
maxd=k;
MaxdLine.topx=(*TempLine).topx;
MaxdLine.topy=(*TempLine).topy;
MaxdLine.botx=(*TempLine).botx;
MaxdLine.boty=(*TempLine).boty;
}
}

hDc = GetDC(hWnd);
rhp = CreatePenIndirect(&amp;rlp);
SelectObject(hDc,rhp);
MoveToEx(hDc,MaxdLine.botx,MaxdLine.boty,NULL);
LineTo(hDc,MaxdLine.topx,MaxdLine.topy);
DeleteObject(rhp);
ReleaseDC(hWnd,hDc);

GlobalUnlock(hImgData);
GlobalUnlock(hDistAlpha);
GlobalFree(hDistAlpha);
GlobalUnlock(hMyLine);
GlobalFree(hMyLine);
return TRUE;
}
////////////////////////////////////////////////////////////////
BOOL LapOfGauss(HWND hWnd)
{
DWORD OffBits,BufSize;
LPBITMAPINFOHEADER lpImgData;
LPSTR lpPtr;
HLOCAL hTempImgData;
LPBITMAPINFOHEADER lpTempImgData;
LPSTR lpTempPtr;
HDC hDc;
HFILE hf;
LONG x,y;
float coef;
float TempNum;

coef=(float)(1.0);

OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);
BufSize=bf.bfSize-sizeof(BITMAPFILEHEADER);

if((hTempImgData=LocalAlloc(LHND,BufSize))==NULL)
{
MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);

lpPtr=(char *)lpImgData;
lpTempPtr=(char *)lpTempImgData;

memcpy(lpTempPtr,lpPtr,BufSize);

for(y=2;y<bi.biHeight-2;y++)
for(x=2;x<bi.biWidth-2;x++){
lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes)+x;
lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-y*LineBytes)+x;
TempNum=(float)((unsigned char)*(lpPtr+2*LineBytes-2))*Template_Log[0];
TempNum+=(float)((unsigned char)*(lpPtr+2*LineBytes-1))*Template_Log[1];
TempNum+=(float)((unsigned char)*(lpPtr+2*LineBytes))*Template_Log[2];
TempNum+=(float)((unsigned char)*(lpPtr+2*LineBytes+1))*Template_Log[3];
TempNum+=(float)((unsigned char)*(lpPtr+2*LineBytes+2))*Template_Log[4];

TempNum+=(float)((unsigned char)*(lpPtr+LineBytes-2))*Template_Log[5];
TempNum+=(float)((unsigned char)*(lpPtr+LineBytes-1))*Template_Log[6];
TempNum+=(float)((unsigned char)*(lpPtr+LineBytes))*Template_Log[7];
TempNum+=(float)((unsigned char)*(lpPtr+LineBytes+1))*Template_Log[8];
TempNum+=(float)((unsigned char)*(lpPtr+LineBytes+2))*Template_Log[9];

TempNum+=(float)((unsigned char)*(lpPtr-2))*Template_Log[10];
TempNum+=(float)((unsigned char)*(lpPtr-1))*Template_Log[11];
TempNum+=(float)((unsigned char)*(lpPtr))*Template_Log[12];
TempNum+=(float)((unsigned char)*(lpPtr+1))*Template_Log[13];
TempNum+=(float)((unsigned char)*(lpPtr+2))*Template_Log[14];

TempNum+=(float)((unsigned char)*(lpPtr-LineBytes-2))*Template_Log[15];
TempNum+=(float)((unsigned char)*(lpPtr-LineBytes-1))*Template_Log[16];
TempNum+=(float)((unsigned char)*(lpPtr-LineBytes))*Template_Log[17];
TempNum+=(float)((unsigned char)*(lpPtr-LineBytes+1))*Template_Log[18];
TempNum+=(float)((unsigned char)*(lpPtr-LineBytes+2))*Template_Log[19];

TempNum+=(float)((unsigned char)*(lpPtr-2*LineBytes-2))*Template_Log[20];
TempNum+=(float)((unsigned char)*(lpPtr-2*LineBytes-1))*Template_Log[21];
TempNum+=(float)((unsigned char)*(lpPtr-2*LineBytes))*Template_Log[22];
TempNum+=(float)((unsigned char)*(lpPtr-2*LineBytes+1))*Template_Log[23];
TempNum+=(float)((unsigned char)*(lpPtr-2*LineBytes+2))*Template_Log[24];

TempNum*=coef;
if(TempNum>255.0) *lpTempPtr=(BYTE)255;
else if(TempNum<0.0)
*lpTempPtr=(unsigned char)fabs(TempNum);
else *lpTempPtr=(BYTE)TempNum;
}

hDc=GetDC(hWnd);
if(hBitmap!=NULL)
DeleteObject(hBitmap);

hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpTempImgData, (LONG)CBM_INIT,
(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER) +NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS);

hf=_lcreat("c://log.bmp",0);
_lwrite(hf,(LPSTR)&amp;bf,sizeof(BITMAPFILEHEADER));
_lwrite(hf,(LPSTR)lpTempImgData,BufSize);
_lclose(hf);

ReleaseDC(hWnd,hDc);
LocalUnlock(hTempImgData);
LocalFree(hTempImgData);
GlobalUnlock(hImgData);
return TRUE;
}
////////////////////////////////////////////////////////////////
BOOL Contour(HWND hWnd)
{
DWORD OffBits,BufSize;
LPBITMAPINFOHEADER lpImgData;
LPSTR lpPtr;
HLOCAL hTempImgData;
LPBITMAPINFOHEADER lpTempImgData;
LPSTR lpTempPtr;
HDC hDc;
HFILE hf;
LONG x,y;
POINT StartP,CurP;
BOOL found;
int i;
int direct[8][2]={{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1}};

if( NumColors!=256){
MessageBox(hWnd,"Must be a mono bitmap with grayscale palette!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);
BufSize=bf.bfSize-sizeof(BITMAPFILEHEADER);
if((hTempImgData=LocalAlloc(LHND,BufSize))==NULL)
{
MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);
memset(lpTempImgData,(BYTE)255,BufSize);
memcpy(lpTempImgData,lpImgData,OffBits);

found=FALSE;
for (y=0;y<bi.biHeight &amp;&amp; !found; y++){
lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes);
for (x=0;x<bi.biWidth &amp;&amp; !found; x++)
if (*(lpPtr++) ==0) found=TRUE;
}

if(found){
StartP.x=x-1;
StartP.y=y-1;
lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-StartP.y*LineBytes)+StartP.x;
*lpTempPtr=(unsigned char)0;
CurP.x=StartP.x+1;
CurP.y=StartP.y;
lpPtr=(char *)lpImgData+(BufSize-LineBytes-CurP.y*LineBytes)+CurP.x;
if(*lpPtr!=0){
CurP.x=StartP.x+1;
CurP.y=StartP.y+1;
lpPtr=(char *)lpImgData+(BufSize-LineBytes-CurP.y*LineBytes)+CurP.x;
if(*lpPtr!=0){
CurP.x=StartP.x;
CurP.y=StartP.y+1;
}
else{
CurP.x=StartP.x-1;
CurP.y=StartP.y+1;
}
}
while (! ( (CurP.x==StartP.x) &amp;&amp;(CurP.y==StartP.y))){
lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-CurP.y*LineBytes)+CurP.x;
*lpTempPtr=(unsigned char)0;
for(i=0;i<8;i++){
x=CurP.x+direct[0];
y=CurP.y+direct[1];
lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-y*LineBytes)+x;
lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes)+x;
if( ( (*lpPtr==0)&amp;&amp;(*lpTempPtr!=0) ) || ( (x==StartP.x) &amp;&amp;(y==StartP.y)))
if(IsContourP(x,y,lpPtr)){
CurP.x=x;
CurP.y=y;
break;
}
}
}
}

if(hBitmap!=NULL)
DeleteObject(hBitmap);
hDc=GetDC(hWnd);
hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpTempImgData, (LONG)CBM_INIT,
(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER) +NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS);

hf=_lcreat("c://contour.bmp",0);
_lwrite(hf,(LPSTR)&amp;bf,sizeof(BITMAPFILEHEADER));
_lwrite(hf,(LPSTR)lpTempImgData,BufSize);
_lclose(hf);

ReleaseDC(hWnd,hDc);
LocalUnlock(hTempImgData);
LocalFree(hTempImgData);
GlobalUnlock(hImgData);
return TRUE;
}
////////////////////////////////////////////////////////////////
BOOL IsContourP(LONG x,LONG y, char *lpPtr)
{
int num,n,w,e,s;

n=(unsigned char)*(lpPtr+LineBytes);
w=(unsigned char)*(lpPtr-1);
e=(unsigned char)*(lpPtr+1);
s=(unsigned char)*(lpPtr-LineBytes);
num=n+w+e+s;
if(num==0)
return FALSE;

return TRUE;
}
////////////////////////////////////////////////////////////////
BOOL SeedFill(HWND hWnd)
{
DWORD BufSize;
LPBITMAPINFOHEADER lpImgData;
HLOCAL hTempImgData;
LPBITMAPINFOHEADER lpTempImgData;
LPSTR lpTempPtr,lpTempPtr1;
HDC hDc;
HFILE hf;
POINT CurP,NeighborP;

if( NumColors!=256){
MessageBox(hWnd,"Must be a mono bitmap with grayscale palette!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

BufSize=bf.bfSize-sizeof(BITMAPFILEHEADER);

if((hTempImgData=LocalAlloc(LHND,BufSize))==NULL)
{
MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);
//copy image data
memcpy(lpTempImgData,lpImgData,BufSize);

if(!InitStack(hWnd,(LONG)bi.biHeight*bi.biWidth)){
LocalUnlock(hTempImgData);
LocalFree(hTempImgData);
GlobalUnlock(hImgData);
return FALSE;
}

lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-SeedPoint.y*LineBytes)+SeedPoint.x;
if(*lpTempPtr==0){
MessageBox(hWnd,"The point you select is a contour point!","Error Message",MB_OK|MB_ICONEXCLAMATION);
LocalUnlock(hTempImgData);
LocalFree(hTempImgData);
GlobalUnlock(hImgData);
DeInitStack();
return FALSE;
}

MyPush(SeedPoint);
while(!IsStackEmpty())
{
CurP=MyPop();
lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-CurP.y*LineBytes)+CurP.x;
*lpTempPtr=(unsigned char)0;
//left neighbour
if(CurP.x>0)
{
NeighborP.x=CurP.x-1;
NeighborP.y=CurP.y;
lpTempPtr1=lpTempPtr-1;
if(*lpTempPtr1!=0)
MyPush(NeighborP);
}
//up neighbour
if(CurP.y>0)
{
NeighborP.x=CurP.x;
NeighborP.y=CurP.y-1;
lpTempPtr1=lpTempPtr+LineBytes;
if(*lpTempPtr1!=0)
MyPush(NeighborP);
}
//right neighbour
if(CurP.x<bi.biWidth-1)
{
NeighborP.x=CurP.x+1;
NeighborP.y=CurP.y;
lpTempPtr1=lpTempPtr+1;
if(*lpTempPtr1!=0)
MyPush(NeighborP);
}
//down neighbour
if(CurP.y<bi.biHeight-1)
{
NeighborP.x=CurP.x;
NeighborP.y=CurP.y+1;
lpTempPtr1=lpTempPtr-LineBytes;
if(*lpTempPtr1!=0)
MyPush(NeighborP);
}
}
DeInitStack();

if(hBitmap!=NULL)
DeleteObject(hBitmap);
hDc=GetDC(hWnd);
hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpTempImgData, (LONG)CBM_INIT,
(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER) +NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS);

hf=_lcreat("c://seed.bmp",0);
_lwrite(hf,(LPSTR)&amp;bf,sizeof(BITMAPFILEHEADER));
_lwrite(hf,(LPSTR)lpTempImgData,BufSize);
_lclose(hf);

ReleaseDC(hWnd,hDc);
LocalUnlock(hTempImgData);
LocalFree(hTempImgData);
GlobalUnlock(hImgData);
return TRUE;
}
////////////////////////////////////////////////////////////////
BOOL InitStack(HWND hWnd,LONG StackLen)
{
SeedFillStack.ElementsNum=StackLen;
if((SeedFillStack.hMem=GlobalAlloc(GHND,SeedFillStack.ElementsNum*sizeof(POINT)))==NULL)
{
MessageBox(hWnd,"Error alloc memory!","ErrorMessage",MB_OK|
MB_ICONEXCLAMATION);
return FALSE;
}
SeedFillStack.lpMyStack=(POINT *)GlobalLock(SeedFillStack.hMem);
memset(SeedFillStack.lpMyStack,0,SeedFillStack.ElementsNum*sizeof(POINT));
SeedFillStack.ptr=0;
return TRUE;
}
////////////////////////////////////////////////////////////////
void DeInitStack()
{
GlobalUnlock(SeedFillStack.hMem);
GlobalFree(SeedFillStack.hMem);
SeedFillStack.ElementsNum=0;
SeedFillStack.ptr=0;
}
////////////////////////////////////////////////////////////////
BOOL MyPush(POINT p)
{
POINT *TempPtr;
if(SeedFillStack.ptr>=SeedFillStack.ElementsNum)
return FALSE;
TempPtr=(POINT *)(SeedFillStack.lpMyStack+SeedFillStack.ptr++);
(*TempPtr).x=p.x;
(*TempPtr).y=p.y;
return TRUE;
}
////////////////////////////////////////////////////////////////
POINT MyPop()
{
POINT InvalidP;
InvalidP.x=-1;
InvalidP.y=-1;

if(SeedFillStack.ptr<=0)
return InvalidP;
SeedFillStack.ptr--;
return *(SeedFillStack.lpMyStack+SeedFillStack.ptr);
}
////////////////////////////////////////////////////////////////
BOOL IsStackEmpty()
{
return (SeedFillStack.ptr==0)?TRUE:FALSE;
}
 
procedure Calc(Bmp, Res: TBitmap; x, y: Integer);
var
Value: Integer;

function Pixels(x, y: Integer): Integer;
begin
if (x < 0) or (x >= Bmp.Width) or
(y < 0) or (y >= Bmp.Height) then
Result := 0
else
Result := Integer(PByteArray(Bmp.ScanLine[y])[x]);
end;

procedure SetPixels(Value: Byte);
begin
PByteArray(Res.ScanLine[y])[x] := Value;
end;

begin
Value := 8 * Pixels(x, y) - (
Pixels(x - 1, y - 1) + Pixels(x, y - 1)
+ Pixels(x + 1, y - 1) + Pixels(x - 1, y)
+ Pixels(x + 1, y) + Pixels(x - 1, y + 1)
+ Pixels(x, y + 1) + Pixels(x + 1, y + 1));
if Value < T then SetPixels(0) //T为阈值,一般取128
else SetPixels(255);
end;

var
Bmp, Res: TBitmap;
begin
Bmp := TBitmap.Create;
Res := TBitmap.Create;
try
Bmp.LoadFromFile(SourceFile); //假设Bmp是256色,其它情况可以进行类似处理
Res.Width := Bmp.Width;
Res.Height := Bmp.Height;
for j := 0 to Bmp.Height - 1 do
for i := 0 to Bmp.Width - 1 do
Calc(Bmp, Res, i, j);
Res.SaveToFile(DestFile);
finally
Res.Free;
Bmp.Free;
end;
end;
 
以下是我的专利:
自己定义的函数和过程:
function Set255(Clr : integer) : integer;
asm
MOV EAX,Clr // store value in EAX register (32-bit register)
CMP EAX,254 // compare it to 254
JG @SETHI // if greater than 254 then go set to 255 (max value)
CMP EAX,1 // if less than 255, compare to 1
JL @SETLO // if less than 1 go set to 0 (min value)
RET // otherwise it doesn't change, just exit
@SETHI: // Set value to 255
MOV EAX,255 // Move 255 into the EAX register
RET // Exit (result value is the EAX register value)
@SETLO: // Set value to 0
MOV EAX,0 // Move 0 into EAX register
end; // Result is in EAX


procedure ConvolveE(ray : array of integer; z : word; aBmp : TBitmap);
var
O, T, C, B : pRGBArray;
x, y : integer;
tBufr : TBitmap;
begin
tBufr := TBitmap.Create;
tBufr.Width:=aBmp.Width+2;
tBufr.Height:=aBmp.Height+2;
tBufr.PixelFormat := pf24bit;
O := aBmp.ScanLine[0];
T := tBufr.ScanLine[0];
T[0] := O[0];
T[tBufr.Width - 1] := O[aBmp.Width - 1];
// Copy top lines
tBufr.Canvas.CopyRect(RECT(1,0,tBufr.Width - 2,1),aBmp.Canvas,
RECT(0,0,aBmp.Width-1,1));
O := aBmp.ScanLine[aBmp.Height - 1];
T := tBufr.ScanLine[tBufr.Height - 1];
T[0] := O[0];
T[tBufr.Width - 1] := O[aBmp.Width - 1];
// Copy bottoms
tBufr.Canvas.CopyRect(RECT(1,tBufr.Height-2,tBufr.Width - 2,tBufr.Height-1),
aBmp.Canvas,RECT(0,aBmp.Height-2,aBmp.Width-1,aBmp.Height-1));
// Copy rights
tBufr.Canvas.CopyRect(RECT(tBufr.Width-2,1,tBufr.Width-1,tBufr.Height-2),
aBmp.Canvas,RECT(aBmp.Width-2,0,aBmp.Width-1,aBmp.Height-1));
// Copy lefts
tBufr.Canvas.CopyRect(RECT(0,1,1,tBufr.Height-2),
aBmp.Canvas,RECT(0,0,1,aBmp.Height-1));
// copy main rectangle
tBufr.Canvas.CopyRect(RECT(1,1,tBufr.Width - 2,tBufr.Height - 2),
aBmp.Canvas,RECT(0,0,aBmp.Width-1,aBmp.Height-1));
for y := 0 to aBmp.Height - 1 do begin
O := aBmp.ScanLine[y];
T := tBufr.ScanLine[y];
C := tBufr.ScanLine[y+1];
B := tBufr.ScanLine[y+2];
for x := 1 to (tBufr.Width - 2) do
begin
if (not TaoSuoBtnDown) or (PtInRegion(MyHrgn1,MyRect.Left+x,MyRect.Top+y)) then
begin
O[x-1].rgbtRed := Set255(
((T[x-1].rgbtRed*ray[0]) +
(T[x].rgbtRed*ray[1]) + (T[x+1].rgbtRed*ray[2]) +
(C[x-1].rgbtRed*ray[3]) +
(C[x].rgbtRed*ray[4]) + (C[x+1].rgbtRed*ray[5])+
(B[x-1].rgbtRed*ray[6]) +
(B[x].rgbtRed*ray[7]) + (B[x+1].rgbtRed*ray[8])) div z
);
O[x-1].rgbtBlue := Set255(
((T[x-1].rgbtBlue*ray[0]) +
(T[x].rgbtBlue*ray[1]) + (T[x+1].rgbtBlue*ray[2]) +
(C[x-1].rgbtBlue*ray[3]) +
(C[x].rgbtBlue*ray[4]) + (C[x+1].rgbtBlue*ray[5])+
(B[x-1].rgbtBlue*ray[6]) +
(B[x].rgbtBlue*ray[7]) + (B[x+1].rgbtBlue*ray[8])) div z
);
O[x-1].rgbtGreen := Set255(
((T[x-1].rgbtGreen*ray[0]) +
(T[x].rgbtGreen*ray[1]) + (T[x+1].rgbtGreen*ray[2]) +
(C[x-1].rgbtGreen*ray[3]) +
(C[x].rgbtGreen*ray[4]) + (C[x+1].rgbtGreen*ray[5])+
(B[x-1].rgbtGreen*ray[6]) +
(B[x].rgbtGreen*ray[7]) + (B[x+1].rgbtGreen*ray[8])) div z
);
end;
end;
end;
tBufr.Free;
end;

进行图象的边缘检测:
procedure EdgeInspection(Bmp:TBitmap);
var
ray:array[0..8]of integer;
z:word;
begin
ray[0] := 1; ray[1] := 1; ray[2] := 1;
ray[3] := 1; ray[4] := -2; ray[5] := 1;
ray[6] := -1; ray[7] := -1; ray[8] := -1;
z := 1;
ConvolveE(ray,z,BmpBuffer);
Bmp:=TBitmap.Create;
Bmp.Assign(BmpBuffer);
end;

边缘增强:
procedure EdgeEnhance(Bmp:TBitmap);
var
ray:array[0..8]of integer;
z:word;
begin
ray[0] := 0; ray[1] := -1; ray[2] := 0;
ray[3] := -1; ray[4] := 5; ray[5] := -1;
ray[6] := 0; ray[7] := -1; ray[8] := 0;
z := 1;
ConvolveE(ray,z,BmpBuffer);
Bmp:=TBitmap.Create;
Bmp.Assign(BmpBuffer);
end;
实质上就是利用了卷积,通常是定义一个3x3的卷积模板!
其余的步骤应该免了吧?!
 
Sorry,有点改动:以下是我的专利:
自己定义的函数和过程:
function Set255(Clr : integer) : integer;
asm
MOV EAX,Clr // store value in EAX register (32-bit register)
CMP EAX,254 // compare it to 254
JG @SETHI // if greater than 254 then go set to 255 (max value)
CMP EAX,1 // if less than 255, compare to 1
JL @SETLO // if less than 1 go set to 0 (min value)
RET // otherwise it doesn't change, just exit
@SETHI: // Set value to 255
MOV EAX,255 // Move 255 into the EAX register
RET // Exit (result value is the EAX register value)
@SETLO: // Set value to 0
MOV EAX,0 // Move 0 into EAX register
end; // Result is in EAX


procedure ConvolveE(ray : array of integer; z : word; aBmp : TBitmap);
var
O, T, C, B : pRGBArray;
x, y : integer;
tBufr : TBitmap;
begin
tBufr := TBitmap.Create;
tBufr.Width:=aBmp.Width+2;
tBufr.Height:=aBmp.Height+2;
tBufr.PixelFormat := pf24bit;
O := aBmp.ScanLine[0];
T := tBufr.ScanLine[0];
T[0] := O[0];
T[tBufr.Width - 1] := O[aBmp.Width - 1];
// Copy top lines
tBufr.Canvas.CopyRect(RECT(1,0,tBufr.Width - 2,1),aBmp.Canvas,
RECT(0,0,aBmp.Width-1,1));
O := aBmp.ScanLine[aBmp.Height - 1];
T := tBufr.ScanLine[tBufr.Height - 1];
T[0] := O[0];
T[tBufr.Width - 1] := O[aBmp.Width - 1];
// Copy bottoms
tBufr.Canvas.CopyRect(RECT(1,tBufr.Height-2,tBufr.Width - 2,tBufr.Height-1),
aBmp.Canvas,RECT(0,aBmp.Height-2,aBmp.Width-1,aBmp.Height-1));
// Copy rights
tBufr.Canvas.CopyRect(RECT(tBufr.Width-2,1,tBufr.Width-1,tBufr.Height-2),
aBmp.Canvas,RECT(aBmp.Width-2,0,aBmp.Width-1,aBmp.Height-1));
// Copy lefts
tBufr.Canvas.CopyRect(RECT(0,1,1,tBufr.Height-2),
aBmp.Canvas,RECT(0,0,1,aBmp.Height-1));
// copy main rectangle
tBufr.Canvas.CopyRect(RECT(1,1,tBufr.Width - 2,tBufr.Height - 2),
aBmp.Canvas,RECT(0,0,aBmp.Width-1,aBmp.Height-1));
for y := 0 to aBmp.Height - 1 do begin
O := aBmp.ScanLine[y];
T := tBufr.ScanLine[y];
C := tBufr.ScanLine[y+1];
B := tBufr.ScanLine[y+2];
for x := 1 to (tBufr.Width - 2) do
begin
//if (not TaoSuoBtnDown) or (PtInRegion(MyHrgn1,MyRect.Left+x,MyRect.Top+y)) then
//begin
O[x-1].rgbtRed := Set255(
((T[x-1].rgbtRed*ray[0]) +
(T[x].rgbtRed*ray[1]) + (T[x+1].rgbtRed*ray[2]) +
(C[x-1].rgbtRed*ray[3]) +
(C[x].rgbtRed*ray[4]) + (C[x+1].rgbtRed*ray[5])+
(B[x-1].rgbtRed*ray[6]) +
(B[x].rgbtRed*ray[7]) + (B[x+1].rgbtRed*ray[8])) div z
);
O[x-1].rgbtBlue := Set255(
((T[x-1].rgbtBlue*ray[0]) +
(T[x].rgbtBlue*ray[1]) + (T[x+1].rgbtBlue*ray[2]) +
(C[x-1].rgbtBlue*ray[3]) +
(C[x].rgbtBlue*ray[4]) + (C[x+1].rgbtBlue*ray[5])+
(B[x-1].rgbtBlue*ray[6]) +
(B[x].rgbtBlue*ray[7]) + (B[x+1].rgbtBlue*ray[8])) div z
);
O[x-1].rgbtGreen := Set255(
((T[x-1].rgbtGreen*ray[0]) +
(T[x].rgbtGreen*ray[1]) + (T[x+1].rgbtGreen*ray[2]) +
(C[x-1].rgbtGreen*ray[3]) +
(C[x].rgbtGreen*ray[4]) + (C[x+1].rgbtGreen*ray[5])+
(B[x-1].rgbtGreen*ray[6]) +
(B[x].rgbtGreen*ray[7]) + (B[x+1].rgbtGreen*ray[8])) div z
);
//end;
end;
end;
tBufr.Free;
end;

进行图象的边缘检测:
procedure EdgeInspection(Bmp:TBitmap);
var
ray:array[0..8]of integer;
z:word;
begin
ray[0] := 1; ray[1] := 1; ray[2] := 1;
ray[3] := 1; ray[4] := -2; ray[5] := 1;
ray[6] := -1; ray[7] := -1; ray[8] := -1;
z := 1;
ConvolveE(ray,z,BmpBuffer);
Bmp:=TBitmap.Create;
Bmp.Assign(BmpBuffer);
end;

边缘增强:
procedure EdgeEnhance(Bmp:TBitmap);
var
ray:array[0..8]of integer;
z:word;
begin
ray[0] := 0; ray[1] := -1; ray[2] := 0;
ray[3] := -1; ray[4] := 5; ray[5] := -1;
ray[6] := 0; ray[7] := -1; ray[8] := 0;
z := 1;
ConvolveE(ray,z,BmpBuffer);
Bmp:=TBitmap.Create;
Bmp.Assign(BmpBuffer);
end;
实质上就是利用了卷积,通常是定义一个3x3的卷积模板!
其余的步骤应该免了吧?!
 
lczhuohuo:可以继续或结束了。
 
多人接受答案了。
 
pRGBarray是自己定义的记录吗?
我用给出的源码好像提示没有这个声明?
 
后退
顶部