您现在的位置:网站首页 > 经验分享 > 二值图像轮廓跟踪源码
设计师介绍:

昵称:烦夫子
类别:界面/平面设计师
年龄:38
现所在地:北京

查看该设计师的主页>>

关注好友

统计中心

主页浏览总数:24254
总积分:89
文章数:88
作品数:70

二值图像轮廓跟踪源码

作者:烦夫子  更新时间: 2007-11-19   浏览人数:19318  评论:1  
分享到:

//Image.cpp 98-8-8
//处理轮廓图像所对应的矢量图
//采用轮廓跟踪法进行处理


#include "stdafx.h"
#include "stdio.h"
#include "osm2view.h"
#include "image.h"
#include "global.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


#define FRAME 50
#define MAX_LENTIMES 2
#define MAX_POINT_PER_CIRCLE 20000
#define MIN_GAP 15
#define LINE_LEN 14 // must be even
#define DEC_COUNT 1 // the times of continuely decreasing
#define MAX_DEN 8 // the max distance between two inflections
#define ERR_MEM 10
#define ERR_FILE 11
#define ERR_BMP 12
#define ERR_PIXEL 13
#define ERR_SIZE 14
#define ERR_UNKNOW 15
#define M_PI 3.1415926

// the current circle and the number of point in current circle
int NumCnt, TotalPoint;
float Skew_K, Dpm_K; //Temp for Adjust Scanor

OutPoint::OutPoint (float _x, float _y)
{
//First :: Adjust
y = _y * YScale;
x = _x * XScale + y * Skew_K;
//Second :: Logical to World
y *= Dpm_K;
x *= Dpm_K;
}

/*-------------------------------------------------------*/

Image::Image ()
{
SizeX = SizeY = NumContour = 0; //图像大小、轮廓数初始化
NumJiDian = NumOrphan = NumHole = 0; //结点、孤立点、孔数初始化
Scale = 0.2; //像素的比例
view = NULL;
pDC = NULL;
P = NULL; //指向像素点数组的指针 白色点
}

//释放内存
void Image::Flush ()
{
//释放结点,像素点所占的内存
for (int i = NumContour - 1; i >= 0; i--) {
delete [] CN[i];
delete [] CY[i];
delete [] CX[i];
}

//按图像尺寸删除
for (i = 0; i < SizeY; i++)
delete [] P[SizeY - i - 1];
if (SizeY > 0) delete [] P;

//赋初值
Scale = 0.2;
SizeX = SizeY = 0;
NumContour = NumJiDian = NumOrphan = NumHole = 0;
view = NULL;
pDC = NULL;
}


//载入轮廓图像
int Image::LoadCnt (LPSTR Name)
{
int j, k, Nump;
DWORD wd;

//打开轮廓图并读入元素
FILE *cnt = fopen (Name, "rb");
if (!cnt) return ERR_FILE;

fread (&wd, sizeof(WORD), 1, cnt);
SizeX = wd;
fread (&wd, sizeof(WORD), 1, cnt);
SizeY = wd;
fread (&wd, sizeof(WORD), 1, cnt);
DPM = wd;

//适配到当前窗口显示
FitToWindow ();

//为要显示的像素分配内存
P = new PACK_IMAGE[SizeY];

for (j = 0; j < SizeY; j++) {
//读入一行或一列
fread (&wd, sizeof(WORD), 1, cnt);
Nump = wd;
//为点数组分配内存
//fread (&Nump, sizeof(int), 1, cnt);
P[j] = new PtArray[Nump + 1];
P[j][0].col = Nump; //计算黑点的列数

//读入点数组并画出轮廓像素
for (k = 0; k < Nump; k++) {
fread (&wd, sizeof(WORD), 1, cnt);
P[j][k+1].col = wd;
P[j][k+1].order = -1;
//if(pDC) pDC->SetPixel (P[j][k+1].col * Scale, j * Scale, RGB (0, 0, 0));
if(pDC) pDC->SetPixel (j * Scale, P[j][k+1].col * Scale, RGB (0, 0, 0));
}
}
//读入轮廓的比例,角度
fread(&XScale, sizeof(float), 1, cnt);
fread(&YScale, sizeof(float), 1, cnt);
fread(&Skew, sizeof(float), 1, cnt);

//关闭轮廓文件,已读入数组中
fclose (cnt);

return 0;
}

//Cnt输出不旋转90,因为下次读入时无法判断是否转过
//保存BMP图像成为轮廓图文件,矢量文件
void Image::SaveBmpToCnt (LPSTR Name)
{
//赋文件名,后缀为PNT
char *p = strrchr (Name, '.');
if (p != NULL) *p = 0;
strcat (Name, ".PNT");

/* .PNT file format (binary)
(SizeX, SizeY, DPM)
(number of points in first row - int)
(X-coord. of point-1 - int)
......
(X-coord. of point-n - int)
......
(number of points in last row - int)
(X-coord. of point-1 - int)
......
(X-coord. of point-n - int)
(XScale, YScale, Skew)
*/

int j, k, Nump;
WORD wd;

//内存中打开一个文件,取名为WB
FILE *cnt = fopen (Name, "wb");
if (!cnt) return ;//ERR_FILE

//写入数据
wd = SizeX;
fwrite (&wd, sizeof(WORD), 1, cnt);
wd = SizeY;
fwrite (&wd, sizeof(WORD), 1, cnt);
wd = DPM;
fwrite (&wd, sizeof(WORD), 1, cnt);

//写入点坐标
for (j = 0; j < SizeY; j++) {
Nump = P[j][0].col;
wd = Nump;
fwrite (&wd, sizeof(WORD), 1, cnt);
for (k = 0; k < Nump; k++) {
wd = P[j][k+1].col;
fwrite (&wd, sizeof(WORD), 1, cnt);
}
}

//写入比例,角度
fwrite (&XScale, sizeof(float), 1, cnt);
fwrite (&YScale, sizeof(float), 1, cnt);
fwrite (&Skew, sizeof(float), 1, cnt);

//关闭文件,释放内存
fclose (cnt);
}

//图像转换,从图像到图形
void Image::Transfer (char *PP[], int Start, int Count)
{
int i, j, k, l, m, index, Ptr, *Buf;

// Temporary store the black pixel in one line
Buf = new int[SizeX];

// Spot erasing 去除沾点
// int SpotPass = 2;
//Gbang Gdadi Guser

/*
if(Gbang == 1)
{
SpotPass = 0;
DilationPass = 0;
}

else if(Gdadi == 1)
{
SpotPass = 1;
DilationPass = 1;
}

else if(Guser == 1)
{
SpotPass;
DilationPass;
}
*/
for (k = 0; k < SpotPass; k++) {
for (i = 1; i < Count + 1; i++)
for (j = 1; j < SizeX - 1; j++) {
int MeanValue = PP[i-1][j-1] + PP[i-1][j] + PP[i-1][j+1] +
PP[i][j-1] + PP[i][j+1] +
PP[i+1][j-1] + PP[i+1][j] + PP[i+1][j+1];
// If the difference between the point-value and mean-value is
// greater than 0.5, then reverse this point
if (PP[i][j] == BLACK) {
if (MeanValue < 4) PP[i][j] = WHITE;
}
else {
if (MeanValue > 4) PP[i][j] = BLACK;
}
}
}

// Image dilating 图像膨胀
for (k = 0; k < DilationPass; k++) {
for (i = 1; i < Count - 1; i++)
for (j = 1; j < SizeX - 1; j++) {
if (PP[i][j] == BLACK) {
for (l = -1; l <= 1; l++)
for (m = -1; m <= 1; m++)
if (PP[i+l][j+m] == WHITE)
PP[i+l][j+m] = BLACK + 2;
}
}
for (i = 0; i < Count + 2; i++)
for (j = 0; j < SizeX; j++)
if (PP[i][j] == BLACK + 2) PP[i][j] = BLACK;
}

// Extracting contour: 提取轮廓 在轮廓线模式下处理
// If all of 4-neighbourhood is black then set this point to white
// This process only for the method "OutLine"
if (Method == 0) { //outline
for (i = 1; i < Count + 1; i++)
for (j = 1; j < SizeX - 1; j++) {
if (PP[i][j] == WHITE) {
j++;
continue;
}
if (PP[i-1][j] >= BLACK && PP[i][j-1] >= BLACK &&
PP[i+1][j] >= BLACK && PP[i][j+1] >= BLACK)
PP[i][j] = BLACK + 1; // This point will be deleted
}
}

if (Count < FRAME - 2) // This is the last block
Count += 2;
//扫描线,提取黑点像素,并存为P点
for (j = Start - 2, i = 0; i < Count; i++, j++) {
// Scan one line, extract the black point and store it to P
for (k = Ptr = 0; k < SizeX; k++)
if (PP[i][k] == BLACK) Buf[Ptr++] = k;

// The image is displaied inversely 反转显示图像
index = j;
P[index] = new PtArray[Ptr + 1];
// The unit 0 store the number of point, that stored in the structure P
//存储点数,并设置矢量点
P[index][0].col = Ptr;
for (k = 0; k < Ptr; k++) {
P[index][k+1].col = Buf[k];
P[index][k+1].order = -1;
//if(pDC) pDC->SetPixel (Buf[k] * Scale, index * Scale, RGB (0, 0, 0));
if(pDC) pDC->SetPixel (index * Scale, Buf[k] * Scale, RGB (0, 0, 0));
}
// Record the number of black points
// total += Ptr;
}
delete [] Buf;
}

(目前有1人发表看法,  我要发表评论
<<上一篇: dxf数据格式输出输出类     下一篇: 图像矢量化源码>>
我要评论:
  只有登录后才能评论!
评论者: 匿名游客    (立即登录 或 注册)