📄 contourtrack.c
字号:
// Ex11
// 轮廓跟踪
#include <windows.h>
#include "image32.h"
#include "stdio.h"
extern HDC hMemDC;
extern struct IMAGE *image;
extern struct IMAGE *Image[10];
void ColorToGray(int m,int n); // 变灰阶
void histog(struct IMAGE *image,long *pg,int Xs, int Ys, int Dx, int Dy);
int Otsu(long *pg,long *pg1);
void GT_Threshold(struct IMAGE *image,int x,int y,int Dx,int Dy,int thre);
#define MAX_DOTN 5000
extern long pg[256],pg1[256];
extern int T_gray[256],thre_v;
HWND hwnd;
int fff,number,fmax,fmin;
long sss;
double factor;
int *code;
struct DOT *dot;
BYTE ThreTable[256];
int code_n,dot_n;
int inc[8][2] = { {+1, 0},{+1,-1},{ 0,-1},{-1,-1},
{-1, 0},{-1,+1},{ 0,+1},{+1,+1} };
int Trx1,Try1,Trx2,Try2;
void set_thre(int track_f, int isr) // 设置阈值标志和阈值
{
int k;
for (k=0;k<256;k++) {
if (track_f==0) {
if (k>isr) ThreTable[k]=0;
else ThreTable[k]=1;
}
else {
if (k<isr) ThreTable[k]=0;
else ThreTable[k]=1;
}
}
}
void delay(int n) // 延时子程序,延时 n 毫秒
{
DWORD StartTime,CurrentTime,m;
StartTime=GetTickCount();
do {
CurrentTime=GetTickCount();
m=(CurrentTime-StartTime);
}
while((int) m<n);
}
void DrawDot(int x,int y,DWORD c)
{
HDC hDC;
hDC = GetDC(hwnd);
SetPixel(hDC,x,y,c);
ReleaseDC(hwnd,hDC);
delay(5);
}
int SingleTrack(struct IMAGE *image,int i, int j, int iop, int *code)
{ // 区域边界跟踪
int kw,code_n;
int curr[2],next[2];
int n,n1;
int ki,kj,inv,ns,ne;
code[0]=i; code[1]=j;
code_n=3;
curr[0]=i; curr[1]=j;
code[3]=-1;
do {
kw=0;
ns=iop; ne=ns-8;
for (n=ns;n>ne;n--) {
n1 = (n+8) % 8;
ki=curr[0]+inc[n1][0];
kj=curr[1]+inc[n1][1];
if ((ki>=Trx1)&&(kj>=Try1)&&(ki<=Trx2)&&(kj<=Try2)) {
inv = getpixel(image,ki, kj);
if (ThreTable[inv]==1) break;
}
}
if (n!=ne) {
next[0]=ki; next[1]=kj;
iop=n1;
DrawDot(ki,kj,0x00ff0000);
}
else kw = 1;
if ((curr[0]==i)&&(curr[1]==j)&&(iop==code[3])) break;
code[code_n++]=iop;
curr[0]=next[0]; curr[1]=next[1];
if (iop%2) iop++;
iop=(iop+1)%8;
}
while(kw==0);
code[2]=code_n-3;
return(code_n-3);
}
int CodeToTable(int *code,struct DOT *dot)
{
int nn[8][8]={
{ 0,0,0,0,2,2,2,2 },
{ 1,1,1,1,0,3,3,3 },
{ 1,1,1,1,0,0,3,3 },
{ 1,1,1,1,0,0,0,3 },
{ 1,1,1,1,0,0,0,0 },
{ 0,3,3,3,2,2,2,2 },
{ 0,0,3,3,2,2,2,2 },
{ 0,0,0,3,2,2,2,2 } };
int i,j,n,k,k1,ki,kj,d;
int dot_n;
dot_n=0;
n=code[2];
code[n+3]=code[3];
ki=code[0]; kj=code[1];
if (n==1) {
dot[0].x=dot[1].x=ki;
dot[0].y=dot[1].y=kj;
return(2);
}
for (i=3;i<n+3;i++) {
k=code[i]%8; k1=code[i+1]%8;
d=nn[k][k1];
ki+=inc[k][0]; kj+=inc[k][1];
if (d!=0) {
dot[dot_n].x =ki;
dot[dot_n++].y=kj;
if (d==3) {
dot[dot_n].x =ki;
dot[dot_n++].y=kj;
}
}
}
for (i=0;i<dot_n-1;i++) {
k=i; n=dot[i].y;
for (j=i+1;j<dot_n;j++) {
if (dot[j].y<n) {
k=j; n=dot[j].y;
}
}
ki=dot[i].x; kj=dot[i].y;
dot[i].x=dot[k].x; dot[i].y=n;
dot[k].x=ki; dot[k].y=kj;
}
for (i=1;i<dot_n;i++) {
for (j=dot_n-1;j>=i;j--) {
if (dot[j-1].y!=dot[j].y) continue;
if (dot[j-1].x>dot[j].x) {
ki=dot[j-1].x; kj=dot[j-1].y;
dot[j-1].x=dot[j].x; dot[j-1].y=dot[j].y;
dot[j].x=ki; dot[j].y=kj;
}
}
}
return(dot_n);
}
int perimeter(int *code)
{
int i,e=0,fff=0,code_n;
code_n=code[2];
for (i=0;i<code_n;i++) {
if ((code[i]%2)==0) fff++;
else e++;
}
fff+=(e*7/5);
return(fff);
}
int area(struct DOT *dot,int dot_n)
{
int i,sss=0;
for (i=0;i<dot_n;i+=2) {
sss+=(dot[i+1].x-dot[i].x+1);
}
return(sss);
}
double form_factor(int fff,int sss)
{
double cv;
cv=(double)fff*fff/sss/12.56;
if (cv<1) cv=1;
return(cv);
}
void fillarea(struct IMAGE *image,struct DOT *dot,int dot_n,int g)
{
int i,j,x,y,wid,hei,c;
LOGPEN lppena = {PS_SOLID,1,1,RGB(0,0,0)};
COLORREF clrref;
HPEN hPen;
if (g<750) c=0;
else c=255;
wid=image->wid;
hei=image->hei;
hMemDC=CreateMemDC();
if (g%512==0) clrref=RGB(0,0,255);
else if (g%512==1) clrref=RGB(0,255,0);
else if (g%512==2) clrref=RGB(255,0,0);
lppena.lopnColor=clrref;
hPen=SelectObject(hMemDC,CreatePenIndirect(&lppena));
for (i=0;i<dot_n;i+=2) {
x=dot[i].x; y=dot[i].y;
j=dot[i+1].x-x+1;
if (j==1) {
SetPixel(hMemDC,x,y,clrref);
setpixel(image,x,y,c);
}
else if ((j>0)&&(x>=0)&&(x<wid)&&(y>=0)&&(y<hei)) {
if (dot[i+1].y==y) {
MoveToEx(hMemDC,x,y,NULL);
LineTo(hMemDC,dot[i+1].x+1,y);
setwin(image,x,y,j,1,c);
}
}
}
DeleteObject(SelectObject(hMemDC,hPen));
DeleteMemDC(hMemDC);
}
void MutiTrack(struct IMAGE *image,int x,int y,int Dx,int Dy,int t)
{
int i,j,c0,c1,c2;
BYTE *sc;
Trx1=x; Try1=y;
Trx2=x+Dx-1; Try2=y+Dy-1;
if (t==0) {
c0=255; c1=1024;
}
else {
c0=0; c1=512;
}
dot =(struct DOT *) malloc(sizeof(struct DOT)*MAX_DOTN);
code=(int*) malloc(sizeof(int)*MAX_DOTN);
sc=malloc(image->bpl);
for (j=y;j<y+Dy-1;j++) {
getimage(image,x,j,Dx,1,sc);
for (i=x;i<x+Dx-1;i++) {
if (ThreTable[sc[i-x]]==1) {
code_n=SingleTrack(image,i,j,4,code);
if (code_n==-1) break;
fff=perimeter(code);
dot_n=CodeToTable(code,dot);
sss=area(dot,dot_n);
factor=form_factor(fff,sss);
if ((fff>fmin)&&(fff<fmax)) {
if ((factor>1.50)&&(fff>145)) c2=2;
else c2=1;
number++;
}
else c2=0;
fillarea(image,dot,dot_n,c1+c2);
getimage(image,x,j,Dx,1,sc);
}
}
}
free(sc);
free(code);
free(dot);
}
int Percent(int *pg,int t)
{
int i,m,n,k;
for (i=0,m=0;i<t;i++) m+=pg[i];
for (i=0,n=0;i<256;i++) n+=pg[i];
k=100*m/n;
return k;
}
void ContourTrack(HWND hWnd)
{
int s,t,u;
char StringT[30];
if ((Image[0]->hdib==NULL)||(Image[0]->bitcount<8)) return;
ClearDDB();
WriteDDB(Image[0], 0, 0, 0, 0,512,512);
ColorToGray(0,1);
histog(Image[1],pg,0,0,Image[1]->wid,Image[1]->hei);
t=Otsu(pg,pg1);
GT_Threshold(Image[1],0,0,Image[1]->wid,Image[1]->hei,t);
fmax=MAX_DOTN-10; fmin=15;
number=0;
u=Percent(pg,t);
if (u<50) s=0;
else {
s=1; u=100-u;
}
if (u>30) return;
hwnd=hWnd;
set_thre(s,t);
MutiTrack(Image[1],0,0,Image[1]->wid,Image[1]->hei,s);
hMemDC=CreateMemDC();
TextOut(hMemDC,600,20,"对象个数",8);
sprintf(StringT,"%5d",number);
TextOut(hMemDC,700,20,StringT,strlen(StringT));
TextOut(hMemDC,600,50,"对象占空比",10);
sprintf(StringT,"%5d %%",u);
TextOut(hMemDC,700,50,StringT,strlen(StringT));
DeleteMemDC(hMemDC);
InvalidateRect(hWnd,NULL,FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -