最近刚刚接触图形方面的东西,真是一无所知:)
我现在想做的就是扫描图像或者曲线,然后判断图中的像素之间的夹角,然后得出链码的数字串值
但是由于不懂图形方面的编程技术,对于怎样取得图中像素和像素的位置都不清楚
请高手指点迷津,帮我如一下门,或者介绍相关比较基础的网站或书籍也好,多谢:)
我现在想做的就是扫描图像或者曲线,然后判断图中的像素之间的夹角,然后得出链码的数字串值
但是由于不懂图形方面的编程技术,对于怎样取得图中像素和像素的位置都不清楚
请高手指点迷津,帮我如一下门,或者介绍相关比较基础的网站或书籍也好,多谢:)
函数名称: Trace
输入参数: bmpIn —— Image类对象,包含要处理图像的所有信息
rgbEdge —— 边缘颜色
ptStart —— 跟踪起始点
输出参数: alEdgePoints —— 边缘点记录
alCode —— 边缘点链码
bmpOut —— Image类对象,传出跟踪得到的边缘,边缘用黑色表示
返回值 : 成功返回true,失败返回false
功能描述: 边缘跟踪(跟踪最外层边缘)
其它说明: 1.程序会生成一个新的Bitmap对象bmpOut,请注意释放
2.输入图像必须是边缘检测后的图象,否则该函数会得到错误结果
3.输入图像要求是二值图像
4.链码的方向如下
2
3 | 1
\ | /
4------+------0
/ | \
5 | 7
6
******************************************************************************/
bool EdgeContour::Trace(Bitmap* bmpIn, Bitmap** bmpOut,
ArrayList** alEdgePoints, ArrayList** alCodes,
Point ptStart, Color rgbEdge)
{
// 检查输入参数
if(bmpIn == NULL || ptStart.X < 0 || ptStart.Y < 0)
{
return false;
} // 循环变量
int x;
int y;
int r; // 存储颜色信息的中间变量
PixelData* pPixelIn; // 输入象素地址
PixelData* pPixelOut; // 输出象素地址 // 临时变量
Color rgbIn1;
Color rgbIn2;
Color rgbTemp;
Color rgbOut; // 当前扫描点
Point ptCurPoint; // 方向数组
int nCurDirection;
int nDirection __nogc[8][2] = {{ 1, 0}, { 1, -1}, {0, -1}, {-1, -1},
{-1, 0}, {-1, 1}, {0, 1}, { 1, 1}}; // 扫描结束标志
bool bFindStartPoint;
bool bFindDirection; // 图像的宽度与高度
int nWidth = bmpIn->Width;
int nHeight = bmpIn->Height; // 待返回的位图对象
(*bmpOut) = new Bitmap(nWidth, nHeight, bmpIn->PixelFormat); // 将图像锁定到内存
BitmapMemory* bmpMemIn = new BitmapMemory(bmpIn);
BitmapMemory* bmpMemOut = new BitmapMemory((*bmpOut)); bmpMemIn->LockBitmap();
bmpMemOut->LockBitmap(); // 检查输入参数
if(ptStart.X < 0 || ptStart.X >= nWidth ||
ptStart.Y < 0 || ptStart.Y >= nHeight)
{
return false;
} // 将返回位图初始化为白色
// 每行
for(y = 0; y < nHeight; y++)
{
// 获取该行首象素颜色值
pPixelOut = bmpMemOut->PixelAt(0, y); // 每列
for(x = 0; x < nWidth; x++)
{
// 填充白色
pPixelOut->byRed = 255;
pPixelOut->byGreen = 255;
pPixelOut->byBlue = 255; pPixelOut++;
}
} pPixelOut = bmpMemOut->PixelAt(ptStart.X, ptStart.Y);
pPixelOut->byRed = 0;
pPixelOut->byGreen = 0;
pPixelOut->byBlue = 0; // 初始化链表
__box Point* ptCurBox;
(*alEdgePoints) = new ArrayList();
(*alCodes) = new ArrayList(); // 初始化当前扫描点
ptCurPoint.X = ptStart.X;
ptCurPoint.Y = ptStart.Y; // 加入第一个点
ptCurBox = __box(ptCurPoint);
(*alEdgePoints)->Add(ptCurBox); // (1)确定初始方向
r = 0;
bFindDirection = false;
nCurDirection = 0;
while(!bFindDirection)
{
pPixelIn = bmpMemIn->PixelAt(ptCurPoint.X + nDirection[nCurDirection][0],
ptCurPoint.Y + nDirection[nCurDirection][1]);
rgbIn1 = Color::FromArgb(pPixelIn->byRed, pPixelIn->byGreen, pPixelIn->byBlue); pPixelIn = bmpMemIn->PixelAt(ptCurPoint.X + nDirection[(nCurDirection + 1) % 8][0],
ptCurPoint.Y + nDirection[(nCurDirection + 1) % 8][1]);
rgbIn2 = Color::FromArgb(pPixelIn->byRed, pPixelIn->byGreen, pPixelIn->byBlue); if(rgbIn1.ToArgb() == rgbEdge.ToArgb() &&
rgbIn2.ToArgb() != rgbEdge.ToArgb())
{
bFindDirection = true;
}
else
{
r++;
nCurDirection = (nCurDirection + 1) % 8; // 防止死循环
if(r > 8)
{
return false;
}
}
} // 修改当前点
ptCurPoint.X += nDirection[nCurDirection][0];
ptCurPoint.Y += nDirection[nCurDirection][1]; bFindStartPoint = false;
do{
// 加入第i+1个点(i=1,2,...)
ptCurBox = __box(ptCurPoint);
(*alEdgePoints)->Add(ptCurBox); // 加入第i个链码(i=1,2,...)
(*alCodes)->Add(__box(nCurDirection)); // (2)保存当前点,为目标点着色
pPixelOut = bmpMemOut->PixelAt(ptCurPoint.X, ptCurPoint.Y);
pPixelOut->byRed = 0;
pPixelOut->byGreen = 0;
pPixelOut->byBlue = 0;; // (4)根据当前点与方向查找下一个边界点
nCurDirection = (nCurDirection + 1) % 8; // 逆时针旋转45度 pPixelIn = bmpMemIn->PixelAt(ptCurPoint.X + nDirection[nCurDirection][0],
ptCurPoint.Y + nDirection[nCurDirection][1]);
rgbTemp = Color::FromArgb(pPixelIn->byRed, pPixelIn->byGreen, pPixelIn->byBlue);
if(rgbTemp.ToArgb() != rgbEdge.ToArgb())
{
// 当前点为白色
// 顺时针旋转45度
nCurDirection = (nCurDirection + 7) % 8; // 初始化
bFindDirection = false; while(!bFindDirection)
{
pPixelIn = bmpMemIn->PixelAt(ptCurPoint.X + nDirection[nCurDirection][0],
ptCurPoint.Y + nDirection[nCurDirection][1]);
rgbIn1 = Color::FromArgb(pPixelIn->byRed, pPixelIn->byGreen, pPixelIn->byBlue);
if(rgbIn1.ToArgb() == rgbEdge.ToArgb())
{
// 修改当前点
ptCurPoint.X += nDirection[nCurDirection][0];
ptCurPoint.Y += nDirection[nCurDirection][1]; bFindDirection = true;
}
else
{
// 顺时针旋转45度
nCurDirection = (nCurDirection + 7) % 8;
}
}
}
else
{
// 当前点为黑色
// 逆时针旋转45度
nCurDirection = (nCurDirection + 1) % 8; // 初始化
bFindDirection = false; while(!bFindDirection)
{
pPixelIn = bmpMemIn->PixelAt(ptCurPoint.X + nDirection[nCurDirection][0],
ptCurPoint.Y + nDirection[nCurDirection][1]);
rgbIn2 = Color::FromArgb(pPixelIn->byRed, pPixelIn->byGreen, pPixelIn->byBlue); if(rgbIn2.ToArgb() != rgbEdge.ToArgb())
{
// 回退操作
nCurDirection = (nCurDirection + 7) % 8; // 修改当前点
ptCurPoint.X += nDirection[nCurDirection][0];
ptCurPoint.Y += nDirection[nCurDirection][1]; bFindDirection = true;
}
else
{
// 逆时针旋转45度
nCurDirection = (nCurDirection + 1) % 8;
}
}
} // (3)判断是否结束
if(ptCurPoint == ptStart)
{
bFindStartPoint = true; // 加入最后一个链码
(*alCodes)->Add(__box(nCurDirection)); break;
} }while(!bFindStartPoint); // 解锁图像
bmpMemIn->UnlockBitmap();
bmpMemOut->UnlockBitmap(); // 成功
return true;
}