如何用C语言实现对图像的二值化?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何用C语言实现对图像的二值化?相关的知识,希望对你有一定的参考价值。

最好有源代码,好的话我肯定追加分数。

/*************************************************************************
* 该函数用于对图像进行阈值分割运算
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
************************************************************************/

BOOL ImageChangeProc::ThresholdDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight)


// 指向源图像的指针
LPSTR lpSrc;

// 指向缓存图像的指针
LPSTR lpDst;

// 指向缓存DIB图像的指针
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;

//循环变量
long i;
long j;

unsigned char pixel;
long lHistogram[256];

//阈值,最大灰度值与最小灰度值,两个区域的平均灰度值
unsigned char Threshold,NewThreshold,MaxGrayValue,MinGrayValue,Temp1GrayValue,Temp2GrayValue;

//用于计算区域灰度平均值的中间变量
long lP1,lP2,lS1,lS2;

//迭代次数
int IterationTimes;

LONG lLineBytes;
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);

if (hNewDIBBits == NULL)

// 分配内存失败
return FALSE;


// 锁定内存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);

// 初始化新分配的内存
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);

lLineBytes = WIDTHBYTES(lWidth * 8);

for (i = 0; i < 256;i++)

lHistogram[i]=0;


//获得直方图
MaxGrayValue = 0;
MinGrayValue = 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(MinGrayValue > pixel)

MinGrayValue = pixel;

if(MaxGrayValue < pixel)

MaxGrayValue = pixel;




//迭代求最佳阈值
NewThreshold = (MinGrayValue + MaxGrayValue)/2;
Threshold = 0;

for(IterationTimes = 0; Threshold != NewThreshold && IterationTimes < 1000;IterationTimes ++)

Threshold = NewThreshold;
lP1 =0;
lP2 =0;
lS1 = 0;
lS2 = 0;
//求两个区域的灰度平均值
for (i = MinGrayValue;i <=Threshold;i++)

lP1 += lHistogram[i]*i;
lS1 += lHistogram[i];


for (i = Threshold+1;i<MaxGrayValue;i++)

lP2 += lHistogram[i]*i;
lS2 += lHistogram[i];

if(lS1==0||lS2==0)

// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return FALSE;

Temp1GrayValue = (unsigned char)(lP1 / lS1);
Temp2GrayValue = (unsigned char)(lP2 / lS2);
NewThreshold = (Temp1GrayValue + Temp2GrayValue)/2;


//根据阈值将图像二值化
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 <= Threshold)

*lpDst = (unsigned char)0;

else

*lpDst = (unsigned char)255;




// 复制图像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);

// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);

// 返回
return TRUE;


参考:http://topic.csdn.net/t/20030909/13/2240079.html
参考技术A query取得iframe中元素的几种方法
在iframe子页面获取父页面元素
代码如下:
$(
参考技术B 1、数字图像处理中,二值化是最简单的。 所谓的二值化一般就是指 将真彩色或者灰度图转化为黑白两色,一般说来是处理灰度图。
2、例如处理灰度图,灰度图像素是从0~255的,假设120是分解,可以将灰度值小于120的像素的灰度值置为0,将灰度值大于120的像素的灰度值置为1,这样整个图像就成了黑白两色了。 二值化的难点不是编程,而是找阈值,这里120就是阈。

图像识别入门5 二值化处理

图像二值化操作在图像处理中有着巨大的作用,常常用于目标的选取;然后图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果。灰度处理后就能够二值化了,这是方便图像处理的重要步骤,对轮廓有要求的很有效。

在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。

 

   OpenCV提供了全局固定阈值和局部自适应阈值的函数来实现二值化图像。 

  全局二值化方法(Global Binariztion Method)对每一幅图计算一个单一的阀值。灰度级大于阈值的像素被标记为背景色,否则为前景。 

  局部二值化方法(Local Adaptive Binarization Method)以像素的邻域的信息为基础来计算每一个像素的阈值。其中一些方法还会计算整个图像中的一个阈值面。如果图像中的一个像素(x,y)的灰度级高于在(x,y)点的阈值面的计算值,那么把像素(x,y)标记为背景,否则为前景字符。

一、 全局二值化方法 threshold

         全局二值化方法 threshold 方法,主要是通过遍历灰度图中点,将图像信息二值化,处理过后的图片只有二种色值。主要介绍全局二值化。

cvThreshold( const CvArr* src, CvArr* dst,double  threshold, double  max_value,int threshold_type );

第一个参数,InputArray类型的src,输入数组,填单通道 , 8或32位浮点类型的Mat即可。

第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放输出结果,且和第一个参数中的Mat变量有一样的尺寸和类型。

第三个参数,double类型的thresh,阈值的具体值。

第四个参数,double类型的maxval,当第五个参数阈值类型type取 THRESH_BINARY 或THRESH_BINARY_INV阈值类型时的最大值.

第五个参数,int类型的type,阈值类型,。

其它参数很好理解,我们来看看第五个参数,第五参数有以下几种类型

0: THRESH_BINARY  当前点值大于阈值时,取Maxval,也就是第四个参数,下面再不说明,否则设置为0

1: THRESH_BINARY_INV 当前点值大于阈值时,设置为0,否则设置为Maxval

2: THRESH_TRUNC 当前点值大于阈值时,设置为阈值,否则不改变

3: THRESH_TOZERO 当前点值大于阈值时,不改变,否则设置为0

4: THRESH_TOZERO_INV  当前点值大于阈值时,设置为0,否则不改变。

/* Threshold types */

enum

{

    CV_THRESH_BINARY      =0,  /* value = value > threshold ? max_value : 0       */

    CV_THRESH_BINARY_INV  =1,  /* value = value > threshold ? 0 : max_value       */

  CV_THRESH_TRUNC       =2,  /* value = value > threshold ? threshold : value   */

    CV_THRESH_TOZERO      =3,  /* value = value > threshold ? value : 0           */

    CV_THRESH_TOZERO_INV  =4,  /* value = value > threshold ? 0 : value           */

     CV_THRESH_MASK        =7,

    CV_THRESH_OTSU        =8  /* use Otsu algorithm to choose the optimal threshold value; combine the flag with one of the above CV_THRESH_* values */

};

注这是opencv2版本五个参数值,opencv3已经有8个参数值,包括OTSU,如下:

当时用thresh_otsu或thresh_triangle,函数确定最优阈值使用Otsu(大津法)或三角形算法,而不是指定的阈值。函数返回Otsu或三角形算法计算得到的阈值。目前,使用大津法和三角法,输入必须为单通道8位的图像。

#include <opencv2/core/core.hpp>  

#include<opencv2/highgui/highgui.hpp>  

#include"opencv2/imgproc/imgproc.hpp"  

#include <iostream>  

using namespace cv;

Mat SrcImage;

Mat GrayImage;

Mat BinaryImage;

 

void on_trackbar(int pos,void*)

{

//转化为二值图

threshold(GrayImage, BinaryImage, pos, 255, CV_THRESH_BINARY);

namedWindow("二值图");

imshow("二值图", BinaryImage);

}

void to_GrayImage()

{

//创建与原图同类型和同大小的矩阵

GrayImage.create(SrcImage.size(), SrcImage.type());

//将原图转换为灰度图像

cvtColor(SrcImage, GrayImage, CV_BGR2GRAY);

 

namedWindow("灰度图");

imshow("灰度图", GrayImage);

}

void creat_trackbar()

{

int nThreshold = 0;

createTrackbar("二值图阈值", "二值图", &nThreshold, 254, on_trackbar);

}

int main()

{

SrcImage = imread("102.jpg");

namedWindow("原图");

imshow("原图", SrcImage);

to_GrayImage();

on_trackbar(1, 0);

creat_trackbar();

waitKey();

}

二、 局部二值化方法  adaptiveThreshold( )

double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type)

1.参数说明:

  src:单通道的输入图像 

  dst:和输入图像同类型的输出图像 

  maxValue: 二值化后非零的最大值设置,二值,顾名思义有两个值,一个是零,一个是(0~256)之间的值。具体和阈值类型搭配说明见下面。 

  adaptiveMethod:自适应阈值算法选择:CV_ADAPTIVE_THRESH_MEAN_C 或CV_ADAPTIVE_THRESH_GAUSSIAN_C。具体说明见下面。 

  thresholdType:阈值类型,下面有详细选择说明。注意,adaptiveThreshold方法只支持前两个参数 

  blockSize:用来计算每个像素的阈值的邻域大小,如3,5,7等。 

  C:从adaptiveMethod选择的方法中计算出来的平均值或加权平均值减去的参数值,可以是正数或负数。区别C方式函数,没有默认值。

2. Opencv实现

与全局阈值法一致,更改对应函数即可。


最后再加个程序

原文:https://blog.csdn.net/MoreWindows/article/details/8239678 :

#include <opencv2/opencv.hpp>

using namespace std;


#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")


IplImage *g_pGrayImage = NULL;

IplImage *g_pBinaryImage = NULL;

const char *pstrWindowsBinaryTitle = "二值图(http://blog.csdn.net/MoreWindows)";


void on_trackbar(int pos)

{

// 转为二值图

cvThreshold(g_pGrayImage, g_pBinaryImage, pos, 255, CV_THRESH_BINARY);

// 显示二值图

cvShowImage(pstrWindowsBinaryTitle, g_pBinaryImage);

}


int main(int argc, char** argv)

{

const char *pstrWindowsSrcTitle = "原图";

const char *pstrWindowsToolBarName = "二值图阈值";


// 从文件中加载原图

IplImage *pSrcImage = cvLoadImage("D:\\abc\\1.jpg", CV_LOAD_IMAGE_UNCHANGED);


// 转为灰度图

g_pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);

cvCvtColor(pSrcImage, g_pGrayImage, CV_BGR2GRAY);


// 创建二值图

g_pBinaryImage = cvCreateImage(cvGetSize(g_pGrayImage), IPL_DEPTH_8U, 1);


// 显示原图

cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);

cvShowImage(pstrWindowsSrcTitle, pSrcImage);

// 创建二值图窗口

cvNamedWindow(pstrWindowsBinaryTitle, CV_WINDOW_AUTOSIZE);


// 滑动条

int nThreshold = 0;

cvCreateTrackbar(pstrWindowsToolBarName, pstrWindowsBinaryTitle, &nThreshold, 254, on_trackbar);


on_trackbar(1);


cvWaitKey(0);


cvDestroyWindow(pstrWindowsSrcTitle);

cvDestroyWindow(pstrWindowsBinaryTitle);

cvReleaseImage(&pSrcImage);

cvReleaseImage(&g_pGrayImage);

cvReleaseImage(&g_pBinaryImage);

return 0;

}

运行结果:(自己动手调试下阈值大小,看看生成的二值图有什么变化。)

以上是关于如何用C语言实现对图像的二值化?的主要内容,如果未能解决你的问题,请参考以下文章

如何用matlab计算二值化图中白色区域的像素点个数

详解-OTUS(大津法-最大类间方差)原理及C语言代码实现

图像的二值化处理的阈值是指啥?求vc下的代码实现!?

怎么用halcon软件来实现图像的二值化呢?

智能车数字图像处理算法入门及C语言实现

如何用c语言printf输出bmp图片的像素信息。