图像二值化----otsu(最大类间方差法、大津算法/最大类间方差法(ostu)图像二值化并获取阈值

在这里插入代//* 函数名称: cvOtsu2D()
//* 函数参数:  CvMat* pGrayMat : 灰度图形相对应的矩阵
//* 返回值 : int nThreshold
//* 函数说明 : 实现灰度图的二值化分割——最大类间方差法(二维Otsu算法/大津算法)
//* 备注:在构建二维直方图的时候,采用灰度点的3 * 3邻域均值

int cvOtsu2D(CvMat *pGrayMat)
{
	double dHistogram[256][256];        //建立二维灰度直方图  
	double dTrMatrix = 0.0;             //离散矩阵的迹
	int height = pGrayMat->rows;
	int width = pGrayMat->cols;
	int N = height*width;               //总像素数
	int i, j;
	for (i = 0; i < 256; i++)
	{
		for (j = 0; j < 256; j++)
			dHistogram[i][j] = 0.0;      //初始化变量  
	}
	for (i = 0; i < height; i++)
	{
		for (j = 0; j < width; j++)
		{
			unsigned char nData1 = (unsigned char)cvGetReal2D(pGrayMat, i, j);//当前的灰度值  
			unsigned char nData2 = 0;
			int nData3 = 0;//注意9个值相加可能超过一个字节                                                                                    
			for (int m = i - 1; m <= i + 1; m++)
			{
				for (int n = j - 1; n <= j + 1; n++)
				{
					if ((m >= 0) && (m < height) && (n >= 0) && (n < width))
						nData3 += (unsigned char)cvGetReal2D(pGrayMat, m, n); //当前的灰度值                                                                        
				}
			}
			nData2 = (unsigned char)(nData3 / 9);    //对于越界的索引值进行补零,邻域均值  
			dHistogram[nData1][nData2]++;
		}
	}
	for (i = 0; i < 256; i++)
		for (j = 0; j < 256; j++)
			dHistogram[i][j] /= N;  //得到归一化的概率分布  

	double Pai = 0.0;      //目标区均值矢量i分量  
	double Paj = 0.0;      //目标区均值矢量j分量  
	double Pbi = 0.0;      //背景区均值矢量i分量  
	double Pbj = 0.0;      //背景区均值矢量j分量  
	double Pti = 0.0;      //全局均值矢量i分量  
	double Ptj = 0.0;      //全局均值矢量j分量  
	double W0 = 0.0;       //目标区的联合概率密度  
	double W1 = 0.0;       //背景区的联合概率密度  
	double dData1 = 0.0;
	double dData2 = 0.0;
	double dData3 = 0.0;
	double dData4 = 0.0;   //中间变量  
	int nThreshold_s = 0;
	int nThreshold_t = 0;
	double temp = 0.0;     //寻求最大值  
	for (i = 0; i < 256; i++)
	{
		for (j = 0; j < 256; j++)
		{
			Pti += i*dHistogram[i][j];
			Ptj += j*dHistogram[i][j];
		}
	}
	for (i = 0; i < 256; i++)
	{
		for (j = 0; j < 256; j++)
		{
			W0 += dHistogram[i][j];
			dData1 += i*dHistogram[i][j];
			dData2 += j*dHistogram[i][j];

			W1 = 1 - W0;
			dData3 = Pti - dData1;
			dData4 = Ptj - dData2;

			Pai = dData1 / W0;
			Paj = dData2 / W0;
			Pbi = dData3 / W1;
			Pbj = dData4 / W1;   // 得到两个均值向量,用4个分量表示  
			dTrMatrix = ((W0 * Pti - dData1) * (W0 * Pti - dData1) + (W0 * Ptj - dData2) * (W0 * Ptj - dData2)) / (W0 * W1);
			if (dTrMatrix > temp)
			{
				temp = dTrMatrix;
				nThreshold_s = i;
				nThreshold_t = j;
			}
		}
	}
	int nThreshold = (nThreshold_s + nThreshold_t) / 2;//返回阈值,有多种形式,可以单独某一个,也可                                                         //是两者的均值 
	return nThreshold;
}




//* 函数名称: 
//* 函数参数: 需要处理的图像的数量:n
//* 返回值 : 无返回值,将处理之后的图片保存起来
//* 函数说明 : 实现采集的原始图像进行中值滤波后二值化并且得到阈值
//* 备注:中值滤波的5 * 5邻域,在膨胀算法使用9 * 9邻域

void  Pict_Proce(int n)
{
	for (int i = 0; i < n; i++)
	{
		//打开图片
		char srcname[100];
		sprintf(srcname, "C:\\Users\\Administrator\\Desktop\\USE__DH\\picture\\焊缝采集原始bmp图片\\%d.bmp", i);
		Mat src1 = imread(srcname,-1);
		if (src1.empty())
			cout << "第" << i << "图片打开失败" << endl;
		else
			cout << "第" << i << "图片打开成功" << endl;
		
		//畸变校正
		Mat src = Picture_jiaozheng(src1);

		//中值滤波
		Mat dst1;
		medianBlur(src, dst1,9);

		//保存滤波后的灰度图
		char save_med_name[100];
		sprintf(save_med_name, "C:\\Users\\Administrator\\Desktop\\USE__DH\\picture\\焊缝图像处理结果\\%d.bmp", i);
		imwrite(save_med_name, dst1);
		cout << "第" << i << "图片处理完成" << endl;

		//迭代法进行图像二值化

		//读取图片
		char dst2_name[100];
		sprintf(dst2_name, "C:\\Users\\Administrator\\Desktop\\USE__DH\\picture\\焊缝图像处理结果\\%d.bmp", i);
		IplImage *img = cvLoadImage(dst2_name, 0);//加载图片
		CvMat *imgMat = cvCreateMat(img->height, img->width, CV_8UC1);//创建矩阵,其type为CV_8UC1
		cvConvert(img, imgMat);//将图像转换成矩阵形式
		int t = cvOtsu2D(imgMat);//求二维阈值分割的阈值
		cout << "第" << i << "幅阈值为" << t << endl;
		cvThreshold(img, img, t, 255, CV_THRESH_BINARY);//用求得的阈值分割图像
		
		cv::Mat dst2 = cv::cvarrToMat(img);

		//二值化图像膨胀
		Mat dst;
		Mat element = getStructuringElement(MORPH_ELLIPSE,Size(9,9));
		dilate(dst2,dst,element);

		//保存最终的图片
		char result_name[100];
		sprintf(result_name, "C:\\Users\\Administrator\\Desktop\\USE__DH\\picture\\焊缝图像处理结果\\result_%d.bmp", i);
		imwrite(result_name, dst);
		cout << "第" << i << "图片二值化完成" << endl;

	}
}
码片

中值滤波之后,将焊缝图像进行二值化并且获得阈值,效果如图。在焊接机器人自动焊接的图像处理中效果很好。在这里插入图片描述在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值