图像二值化----otsu(最大类间方差法)
2017-04-07 10:35
211 查看
/*****转自:http://blog.csdn.net/abcjennifer/article/details/6671288******/最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。它是按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。对于图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图像的比例记为ω0,其平均灰度μ0;背景像素点数占整幅图像的比例为ω1,其平均灰度为μ1。图像的总平均灰度记为μ,类间方差记为g。假设图像的背景较暗,并且图像的大小为M×N,图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1,则有: ω0=N0/ M×N (1) ω1=N1/ M×N (2) N0+N1=M×N (3) ω0+ω1=1 (4) μ=ω0*μ0+ω1*μ1 (5) g=ω0(μ0-μ)^2+ω1(μ1-μ)^2 (6)将式(5)代入式(6),得到等价公式: g=ω0ω1(μ0-μ1)^2 (7)采用遍历的方法得到使类间方差最大的阈值T,即为所求。
Otsu算法步骤如下:设图象包含L个灰度级(0,1…,L-1),灰度值为i的的象素点数为Ni ,图象总的象素点数为N=N0+N1+...+N(L-1)。灰度值为i的点的概为:P(i) = N(i)/N.门限t将整幅图象分为暗区c1和亮区c2两类,则类间方差σ是t的函数:σ=a1*a2(u1-u2)^2 (2)式中,aj 为类cj的面积与图象总面积之比,a1 = sum(P(i)) i->t, a2 = 1-a1; uj为类cj的均值,u1 = sum(i*P(i))/a1 0->t, u2 = sum(i*P(i))/a2, t+1->L-1 该法选择最佳门限t^ 使类间方差最大,即:令Δu=u1-u2,σb = max{a1(t)*a2(t)Δu^2}/****************************************以下部分内容为原创;OTSU代码**********************************************/
#include <stdio.h>
#include <string>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
// OTSU大均法函数实现
int OTSU(cv::Mat srcImage)
{
int nCols = srcImage.cols;
int nRows = srcImage.rows;
int threshold = 0;
// 初始化统计参数
int nSumPix[256];
float nProDis[256];
for (int i = 0; i < 256; i++)
{
nSumPix[i] = 0;
nProDis[i] = 0;
}
// 统计灰度级中每个像素在整幅图像中的个数
for (int i = 0; i < nCols; i++)
{
for (int j = 0; j < nRows; j++)
{
nSumPix[(int)srcImage.at<uchar>(i, j)]++;
}
}
// 计算每个灰度级占图像中的概率分布
for (int i = 0; i < 256; i++)
{
nProDis[i] = (float)nSumPix[i] / (nCols * nRows);
}
// 遍历灰度级[0,255],计算出最大类间方差下的阈值
float w0, w1, u0_temp, u1_temp, u0, u1, delta_temp;
double delta_max = 0.0;
for (int i = 0; i < 256; i++)
{
// 初始化相关参数
w0 = w1 = u0_temp = u1_temp = u0 = u1 = delta_temp = 0;
for (int j = 0; j < 256; j++)
{
//背景部分
if (j <= i)
{
// 当前i为分割阈值,第一类总的概率
w0 += nProDis[j];
u0_temp += j * nProDis[j];
}
//前景部分
else
{
// 当前i为分割阈值,第一类总的概率
w1 += nProDis[j];
u1_temp += j * nProDis[j];
}
}
// 分别计算各类的平均灰度
u0 = u0_temp / w0;
u1 = u1_temp / w1;
delta_temp = (float)(w0 *w1* pow((u0 - u1), 2));
// 依次找到最大类间方差下的阈值
if (delta_temp > delta_max)
{
delta_max = delta_temp;
threshold = i;
}
}
return threshold;
}
int main()
{
// 图像读取及判断
cv::Mat srcImage = cv::imread("..\\images\\people.jpg");
if (!srcImage.data)
return 1;
// 灰度转换
cv::Mat srcGray;
cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY);
cv::imshow("srcGray", srcGray);
// 调用OTSU二值化算法得到阈值
int ostuThreshold = OTSU(srcGray);
std::cout << ostuThreshold << std::endl;
// 定义输出结果图像
cv::Mat otsuResultImage =
cv::Mat::zeros(srcGray.rows, srcGray.cols, CV_8UC1);
// 利用得到的阈值实现二值化操作
for (int i = 0; i < srcGray.rows; i++)
{
for (int j = 0; j < srcGray.cols; j++)
{
// 满足大于阈值ostuThreshold置255
if (srcGray.at<uchar>(i, j) > ostuThreshold)
otsuResultImage.at<uchar>(i, j) = 255;
else
otsuResultImage.at<uchar>(i, j) = 0;
}
}
cv::imshow("otsuResultImage", otsuResultImage);
cv::waitKey(0);
return 0;
}
[plain] view
plain copy
I=imread('D:\Images\pic_loc\1870405130305041503.jpg');
a=rgb2gray(I);
level = graythresh(a);
a=im2bw(a,level);
imshow(a,[]);
Otsu算法步骤如下:设图象包含L个灰度级(0,1…,L-1),灰度值为i的的象素点数为Ni ,图象总的象素点数为N=N0+N1+...+N(L-1)。灰度值为i的点的概为:P(i) = N(i)/N.门限t将整幅图象分为暗区c1和亮区c2两类,则类间方差σ是t的函数:σ=a1*a2(u1-u2)^2 (2)式中,aj 为类cj的面积与图象总面积之比,a1 = sum(P(i)) i->t, a2 = 1-a1; uj为类cj的均值,u1 = sum(i*P(i))/a1 0->t, u2 = sum(i*P(i))/a2, t+1->L-1 该法选择最佳门限t^ 使类间方差最大,即:令Δu=u1-u2,σb = max{a1(t)*a2(t)Δu^2}/****************************************以下部分内容为原创;OTSU代码**********************************************/
#include <stdio.h>
#include <string>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
#include #include #include "opencv2/highgui/highgui.hpp" #include "opencv2/opencv.hpp" using namespace std; using namespace cv; // OTSU大均法函数实现 int OTSU(cv::Mat srcImage) { int nCols = srcImage.cols; int nRows = srcImage.rows; int threshold = 0; // 初始化统计参数 int nSumPix[256]; float nProDis[256]; for (int i = 0; i < 256; i++) { nSumPix[i] = 0; nProDis[i] = 0; } // 统计灰度级中每个像素在整幅图像中的个数 for (int i = 0; i < nCols; i++) { for (int j = 0; j < nRows; j++) { nSumPix[(int)srcImage.at(i, j)]++; } } // 计算每个灰度级占图像中的概率分布 for (int i = 0; i < 256; i++) { nProDis[i] = (float)nSumPix[i] / (nCols * nRows); } // 遍历灰度级[0,255],计算出最大类间方差下的阈值 float w0, w1, u0_temp, u1_temp, u0, u1, delta_temp; double delta_max = 0.0; for (int i = 0; i < 256; i++) { // 初始化相关参数 w0 = w1 = u0_temp = u1_temp = u0 = u1 = delta_temp = 0; for (int j = 0; j < 256; j++) { //背景部分 if (j <= i) { // 当前i为分割阈值,第一类总的概率 w0 += nProDis[j]; u0_temp += j * nProDis[j]; } //前景部分 else { // 当前i为分割阈值,第一类总的概率 w1 += nProDis[j]; u1_temp += j * nProDis[j]; } } // 分别计算各类的平均灰度 u0 = u0_temp / w0; u1 = u1_temp / w1; delta_temp = (float)(w0 *w1* pow((u0 - u1), 2)); // 依次找到最大类间方差下的阈值 if (delta_temp > delta_max) { delta_max = delta_temp; threshold = i; } } return threshold; } int main() { // 图像读取及判断 cv::Mat srcImage = cv::imread("..\\images\\people.jpg"); if (!srcImage.data) return 1; // 灰度转换 cv::Mat srcGray; cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY); cv::imshow("srcGray", srcGray); // 调用OTSU二值化算法得到阈值 int ostuThreshold = OTSU(srcGray); std::cout << ostuThreshold << std::endl; // 定义输出结果图像 cv::Mat otsuResultImage = cv::Mat::zeros(srcGray.rows, srcGray.cols, CV_8UC1); // 利用得到的阈值实现二值化操作 for (int i = 0; i < srcGray.rows; i++) { for (int j = 0; j < srcGray.cols; j++) { // 满足大于阈值ostuThreshold置255 if (srcGray.at(i, j) > ostuThreshold) otsuResultImage.at(i, j) = 255; else otsuResultImage.at(i, j) = 0; } } cv::imshow("otsuResultImage", otsuResultImage); cv::waitKey(0); return 0; }
// OTSU大均法函数实现
int OTSU(cv::Mat srcImage)
{
int nCols = srcImage.cols;
int nRows = srcImage.rows;
int threshold = 0;
// 初始化统计参数
int nSumPix[256];
float nProDis[256];
for (int i = 0; i < 256; i++)
{
nSumPix[i] = 0;
nProDis[i] = 0;
}
// 统计灰度级中每个像素在整幅图像中的个数
for (int i = 0; i < nCols; i++)
{
for (int j = 0; j < nRows; j++)
{
nSumPix[(int)srcImage.at<uchar>(i, j)]++;
}
}
// 计算每个灰度级占图像中的概率分布
for (int i = 0; i < 256; i++)
{
nProDis[i] = (float)nSumPix[i] / (nCols * nRows);
}
// 遍历灰度级[0,255],计算出最大类间方差下的阈值
float w0, w1, u0_temp, u1_temp, u0, u1, delta_temp;
double delta_max = 0.0;
for (int i = 0; i < 256; i++)
{
// 初始化相关参数
w0 = w1 = u0_temp = u1_temp = u0 = u1 = delta_temp = 0;
for (int j = 0; j < 256; j++)
{
//背景部分
if (j <= i)
{
// 当前i为分割阈值,第一类总的概率
w0 += nProDis[j];
u0_temp += j * nProDis[j];
}
//前景部分
else
{
// 当前i为分割阈值,第一类总的概率
w1 += nProDis[j];
u1_temp += j * nProDis[j];
}
}
// 分别计算各类的平均灰度
u0 = u0_temp / w0;
u1 = u1_temp / w1;
delta_temp = (float)(w0 *w1* pow((u0 - u1), 2));
// 依次找到最大类间方差下的阈值
if (delta_temp > delta_max)
{
delta_max = delta_temp;
threshold = i;
}
}
return threshold;
}
int main()
{
// 图像读取及判断
cv::Mat srcImage = cv::imread("..\\images\\people.jpg");
if (!srcImage.data)
return 1;
// 灰度转换
cv::Mat srcGray;
cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY);
cv::imshow("srcGray", srcGray);
// 调用OTSU二值化算法得到阈值
int ostuThreshold = OTSU(srcGray);
std::cout << ostuThreshold << std::endl;
// 定义输出结果图像
cv::Mat otsuResultImage =
cv::Mat::zeros(srcGray.rows, srcGray.cols, CV_8UC1);
// 利用得到的阈值实现二值化操作
for (int i = 0; i < srcGray.rows; i++)
{
for (int j = 0; j < srcGray.cols; j++)
{
// 满足大于阈值ostuThreshold置255
if (srcGray.at<uchar>(i, j) > ostuThreshold)
otsuResultImage.at<uchar>(i, j) = 255;
else
otsuResultImage.at<uchar>(i, j) = 0;
}
}
cv::imshow("otsuResultImage", otsuResultImage);
cv::waitKey(0);
return 0;
}
/****************************************以下内容为MATLAB实现的OTSU代码**********************************************/
[plain] view
plain copy
I=imread('D:\Images\pic_loc\1870405130305041503.jpg');
a=rgb2gray(I);
level = graythresh(a);
a=im2bw(a,level);
imshow(a,[]);
相关文章推荐
- 图像二值化----otsu(最大类间方差法、大津算法)
- 图像二值化方法--OTSU(最大类间方差法)
- 最大类间方差法(OTSU)
- 图像二值化----otsu(最大类间方差法、大津算法)
- OTSU最大类间方差法(求自适应阈值)
- 图像二值化----otsu(最大类间方差法、大津算法)
- 自动选择阈值--最大类间方差法(OTSU)原理及matlab实现
- Otsu(最大类间方差法)方法的C++实现
- 最大类间方差法(OTSU)
- 最大类间方差法OTSU,1979年前后景区分法
- 最大类间方差法(大津法,OTSU)
- Otsu最大类间方差法
- 最大类间方差法(OTSU)
- OTSU最大类间方差法
- 图像二值化----otsu(最大类间方差法、大津算法)
- 最大类间方差法(大津法,OTSU)
- 图像二值化----otsu(最大类间方差法、大津算法)
- 图像二值化----otsu(最大类间方差法、大津算法)
- OpenCV2.x自学笔记——最大类间方差法OTSU
- 图像二值化----otsu(最大类间方差法、大津算法)