二值化是一个相当复杂的理论问题,如果不给出具体的应用要求是无法做的.
最简单的:
for(......)
if(PixelY[i,j]>T)
PixelY[i,j] = 255;
else
PixelY[i,j] = 0;
如果考虑具体问题,二值化算法不下100种.
/***************************************************************************
* 函数名称
* OSTUThreshold()
* 参数
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(像素数)
* LONG lHeight - 源图像高度(像素数)
* 返回值
* BOOL - 运算成功 返回TRUE , 否则 返回FALSE。
* 说明
* 该函数采用大津法进行阈值分割 二值化
***************************************************************************/
BOOL WINAPI OSTUThreshold(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
// 指向源图像像素指针
LPSTR lpSrc;
// 指向缓存图像指针
LPSTR lpDst;
// 指向缓存图像像素指针
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
// 循环变量
int i, j, t;
// 用于计算两个区域的中间变量
long lP1, lS1, lP2, lS2;
// 像素值
unsigned char pixel;
// 灰度直方图数组
long lHistogram[256];
// 阈值, 最大灰度值和最小灰度值, 两个区域的平均灰度值
unsigned char iThreshold, iNewThreshold, iMaxGrayValue, iMinGrayValue, iMean1GrayValue, iMean2GrayValue;
// 前景点数占图像比例, 背景点数占图像比例
double w0,w1;
// 方差
double G, tempG;
// 图像每行占字节数
LONG lLineBytes;
// 暂时分配内存, 以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if (hNewDIBBits == NULL)
{
//分配内存失败
return FALSE;
}
// 锁定内存
lpNewDIBBits = (char *) LocalLock(hNewDIBBits);
// 初始化新分配的内存, 设定初始值为255
lpDst = (char *) lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
lLineBytes = WIDTHBYTES(lWidth * 8);
for(i= 0; i < 256; i++)
{
lHistogram[i] = 0;
}
// 获得灰度直方图,灰度最大值和灰度最小值
iMaxGrayValue = 0;
iMinGrayValue = 255;
for(i = 0; i < lWidth; i++)
{
for(j = 0; j < lHeight; j++)
{
lpSrc = (char *) lpDIBBits + lLineBytes * j + i;
pixel = (unsigned char) *lpSrc;
lHistogram[pixel]++;
// 修改最大灰度值和最小灰度值
if (iMinGrayValue > pixel)
{
iMinGrayValue = pixel;
}
if (iMaxGrayValue < pixel)
{
iMaxGrayValue = pixel;
}
}
}
// 遍历t, 选取最佳阈值
for(t = iMinGrayValue; t < iMaxGrayValue ; t++)
{
iNewThreshold = t;
lP1 = 0;
lS1 = 0;
lP2 = 0;
lS2 = 0;
// 求前景,背景两个区域的平均灰度值, 点数所占比例
for(i = iMinGrayValue; i <= iNewThreshold; i++)
{
lP1 += lHistogram[i] * i;
lS1 += lHistogram[i];
}
iMean1GrayValue = (unsigned char) (lP1/lS1);
w0 = (double) (lS1) / (lWidth * lHeight);
for(i = iNewThreshold + 1; i <= iMaxGrayValue; i++)
{
lP2 += lHistogram[i] * i;
lS2 += lHistogram[i];
}
iMean2GrayValue = (unsigned char) (lP2/lS2);
w1 = 1 - w0;
// 计算类间方差
G = (double) w0 * w1
* (iMean1GrayValue - iMean2GrayValue) * (iMean1GrayValue - iMean2GrayValue);
if (G > tempG)
{
tempG = G;
iThreshold = iNewThreshold;
}
}
// 根据阈值将图像二值化
for(i = 0; i < lWidth; i++)
{
for(j = 0; j < lHeight; j++)
{
lpSrc = (char *) lpDIBBits + lLineBytes * j + i;
lpDst = (char *) lpNewDIBBits + lLineBytes * j + i;
pixel = (unsigned char) *lpSrc;
if (pixel <= iThreshold)
{
*lpDst = (unsigned char)0;
}
else
{
*lpDst = (unsigned char) 255;
}
}
}
// 复制图像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* ThresholdDIB()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
*
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用 迭代法 对图像进行阈值分割运算。
*
************************************************************************/
BOOL WINAPI ThresholdDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight)
{
// 指向源图像的指针
LPSTRlpSrc;
// 指向缓存图像的指针
LPSTRlpDst;
// 指向缓存DIB图像的指针
LPSTRlpNewDIBBits;
HLOCALhNewDIBBits;
//循环变量
long i;
long j;
//像素值
unsigned char pixel;
//直方图数组
long lHistogram[256];
//阈值,最大灰度值与最小灰度值,两个区域的平均灰度值
unsigned char iThreshold,iNewThreshold,iMaxGrayValue,iMinGrayValue,iMean1GrayValue,iMean2GrayValue;
//用于计算区域灰度平均值的中间变量
long lP1,lP2,lS1,lS2;
//迭代次数
int iIterationTimes;
// 图像每行的字节数
LONG lLineBytes;
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if (hNewDIBBits == NULL)
{
// 分配内存失败
return FALSE;
}
// 锁定内存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
for (i = 0; i < 256;i++)
{
lHistogram[i]=0;
}
//获得直方图
iMaxGrayValue = 0;
iMinGrayValue = 255;
for (i = 0;i < lWidth ;i++)
{
for(j = 0;j < lHeight ;j++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
pixel = (unsigned char)*lpSrc;
lHistogram[pixel]++;
//修改最大,最小灰度值
if(iMinGrayValue > pixel)
{
iMinGrayValue = pixel;
}
if(iMaxGrayValue < pixel)
{
iMaxGrayValue = pixel;
}
}
}
//迭代求最佳阈值
iNewThreshold = (iMinGrayValue + iMaxGrayValue)/2;
iThreshold = 0;
for(iIterationTimes = 0; iThreshold != iNewThreshold && iIterationTimes < 100;iIterationTimes ++)
{
iThreshold = iNewThreshold;
lP1 =0;
lP2 =0;
lS1 = 0;
lS2 = 0;
//求两个区域的灰度平均值
for (i = iMinGrayValue;i < iThreshold;i++)
{
lP1 += lHistogram[i]*i;
lS1 += lHistogram[i];
}
iMean1GrayValue = (unsigned char)(lP1 / lS1);
for (i = iThreshold+1;i < iMaxGrayValue;i++)
{
lP2 += lHistogram[i]*i;
lS2 += lHistogram[i];
}
iMean2GrayValue = (unsigned char)(lP2 / lS2);
iNewThreshold = (iMean1GrayValue + iMean2GrayValue)/2;
}
//根据阈值将图像二值化
for (i = 0;i < lWidth ;i++)
{
for(j = 0;j < lHeight ;j++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
pixel = (unsigned char)*lpSrc;
if(pixel <= iThreshold)
{
*lpDst = (unsigned char)0;
}
else
{
*lpDst = (unsigned char)255;
}
}
}
// 复制图像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
///////////////////////////////////////////////////////////////
1、图像的二值化的基本原理
图像的二值化处理就是讲图像上的点的灰度置为0或255,也就是讲整个图像呈现出明显的黑白效果。即将256个亮度等级的灰度图像通过适当的阀值选取而获得仍然可以反映图像整体和局部特征的二值化图像。在数字图像处理中,二值图像占有非常重要的地位,特别是在实用的图像处理中,以二值图像处理实现而构成的系统是很多的,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像,这样子有利于再对图像做进一步处理时,图像的集合性质只与像素值为0或255的点的位置有关,不再涉及像素的多级值,使处理变得简单,而且数据的处理和压缩量小。为了得到理想的二值图像,一般采用封闭、连通的边界定义不交叠的区域。所有灰度大于或等于阀值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。如果某特定物体在内部有均匀一致的灰度值,并且其处在一个具有其他等级灰度值的均匀背景下,使用阀值法就可以得到比较的分割效果。如果物体同背景的差别表现不在灰度值上(比如纹理不同),可以将这个差别特征转换为灰度的差别,然后利用阀值选取技术来分割该图像。动态调节阀值实现图像的二值化可动态观察其分割图像的具体结果。
2、图像的二值化的程序实现
通过Delphi刻度控件调整阀值,实现动态控制,程序如下:
procedure TForm1.Button1Click(Sender: TObject);
var
p:PByteArray;
Gray,x,y:integer;
begin
TestBMP:=TBitmap.Create; changedbmp:=tbitmap.Create;
testbmp.Assign(image1.Picture);
for y:=0 to testbmp.Height-1 do
begin
p:=testbmp.ScanLine[y];
for x:=0 to testbmp.Width-1 do
begin
//首先将图像灰度化
gray:=round(p[x*3+2]*0.3+p[x*3+1]*0.59+p[x*3]*0.11);
if gray> TrackBar1.Position then //按阀值进行二值化
begin
p[x*3]:=255; p[x*3+1]:=255; p[x*3+2]:=255;
end
else
begin
p[x*3]:=0;p[x*3+1]:=0;p[x*3+2]:=0;
end;
end;
end;
ChangedBmp.Assign(TestBMP);
PaintBox1.Canvas.CopyMode:=srccopy;
PaintBox1.Canvas.Draw(0,0,ChangedBmp);
end;
3、处理的效果

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=886749
分享到:
相关推荐
本文将深入探讨图像运算的基本形式,包括点运算、领域运算、并行运算、串行运算、迭代运算、窗口运算、模板运算以及帧运算,并详细介绍其中的点运算和图像的代数、几何运算。 一、图像运算的基本形式 1. 点运算:...
8. Cholesky 分解、矩阵的正定性和 Jacobi、Gauss-Seidel 迭代法的收敛性:(a) 矩阵正定的条件与参数有关,一般要求所有特征值都是正的;(b) Jacobi 迭代的收敛性与矩阵的条件数和结构有关,对于某些矩阵可能是收敛...
文件“有限体积法计算方腔流.doc”很可能是详细介绍了如何应用有限体积法和Quick算法来解决这个问题的步骤,包括网格生成、离散方程的构造、迭代求解过程以及后处理,如速度和压力场的可视化。这样的文档通常会涵盖...
牛顿法是一种二阶优化方法,通过迭代更新来接近函数的局部极小值。它利用函数的梯度和海塞矩阵,形成一个迭代公式,以期望在下一次迭代中更接近最小值。在非线性MPC的框架下,牛顿法可以作为求解非线性优化问题的...
3. **线性方程组**:高斯消元法、克拉默法则、矩阵的逆和伴随矩阵在解线性方程组中的应用,以及迭代方法如高斯-塞德尔和雅可比迭代。 4. **特征值和特征向量**:它们在稳定性分析、振动问题和数据分析中的重要性。...
11. 7.6 浮点数和科学记数法(ios::scientific、ios::fixed) 11.7.7 大/小写控制(ios:uppercase) 11.7.8 设置及清除格式标志(flags、setiosflags、resetiosflags) 11.8 流错误状态 11.9 把输出流连到输入流...
11. 7.6 浮点数和科学记数法(ios::scientific、ios::fixed) 11.7.7 大/小写控制(ios:uppercase) 11.7.8 设置及清除格式标志(flags、setiosflags、resetiosflags) 11.8 流错误状态 11.9 把输出流连到输入流...
C#矩阵库可能会包含求解特征值和特征向量的算法,如幂迭代法或QR分解。 7. **线性方程组求解**:线性方程组的求解是矩阵运算的一大应用场景。C#矩阵库可能提供高斯消元、高斯-约旦消元、LU分解、Cholesky分解等方法...
6. **数值方法与极值问题**:如二分法、三分法、牛顿迭代法、多元函数的偏导计算、拉格朗日乘子法、符号积分和数值积分等,这些方法常用于求解最优化问题和处理复杂的函数关系。 7. **线性代数**:矩阵、行列式、...
综上所述,有限体积法作为一种结合了有限元法和差分法优点的数值方法,在解决实际工程问题时展现出了强大的优势。通过合理选择和设计,有限体积法能够在保持物理守恒性的同时,实现高效稳定的数值求解过程。
对于大型线性方程组,迭代方法如高斯-塞德尔法和共轭梯度法更为实用。 8. 矩阵分解:矩阵分解是将一个矩阵转化为几种特定形式的组合,如奇异值分解(SVD)、QR分解、LU分解等。这些分解在数据分析、图像处理和控制...
- **定义**:计算机图形学是研究如何在计算机上生成图形和图像的一门学科。 - **学科关系**: - **计算机图形学**关注的是图形的生成和渲染。 - **数字图像处理**侧重于对已存在的图像进行处理,如增强、压缩等。 ...
3.2.1 定义和初始化string对象 76 3.2.2 string对象上的操作 77 3.2.3 处理string对象中的字符 81 3.3 标准库类型vector 86 3.3.1 定义和初始化vector对象 87 3.3.2 向vector对象中添加元素 90 3.3.3 ...
3.2.1 定义和初始化string对象 76 3.2.2 string对象上的操作 77 3.2.3 处理string对象中的字符 81 3.3 标准库类型vector 86 3.3.1 定义和初始化vector对象 87 3.3.2 向vector对象中添加元素 90 3.3.3 ...
9.1.5 事务和调度的一种记法 习题 9.2 冲突可串行性 9.2.1 冲突 9.2.2 优先图及冲突可串行性判断 9.2.3 优先图测试发挥作用的原因 习题 9.3 使用锁的可串行性实现 9.3.1 锁 9.3.2 封锁调度器 ...
- (4) 使用幂律拟合(例如最小二乘法)找到最佳的D值,使得N ~ L^(-D)成立。 - (5) 输出分形维数D。 5. **注意事项** - 在实际应用中,可能会遇到数据噪声和有限精度问题,需要对数据进行预处理和误差分析。 - ...
为了确保卫星编队在LEO环境下的稳定性和精确性,研究者们提出了一种基于线性二次调节器(Linear Quadratic Regulator, LQR)方法的线性状态反馈控制律。该算法利用常规的全球定位系统(Global Positioning System, ...
《二维有限体积法在PDE求解中的实现》 有限体积法(Finite Volume Method, FVM)是一种广泛应用的数值计算方法,特别是在解决偏微分方程(Partial Differential Equations, PDEs)的问题中。标题"simple-finite-...
9. **泊松分布与二项分布**:泊松分布是二项分布的极限形式,当试验次数n很大且每次成功概率p很小时,可以用泊松分布近似二项分布。 10. **Python3除法**:Python3中的整数除法5/2结果是2.5。 11. **人工智能应用...
**算法图论**是一门结合了数学和计算机科学的交叉学科,主要研究如何利用算法解决图论中的问题。图是一种由顶点(节点)和边组成的数学结构,能够用来表示各种关系和网络。本书《算法图论》由David Joyner、Minh Van...