图像分割 1.基于阈值的算法

来源:互联网 发布:java while循环 编辑:程序博客网 时间:2024/05/21 00:47


   

  

http://blog.csdn.net/xw20084898/article/details/17564957            主要取自这里,修改为Mat类。

    单阈值图像分割算法,有手动阀值,自适应阈值,最大熵法,基本全局阈值法,OTSU阈值。

#include<opencv2/opencv.hpp>#include<opencv2/imgproc.hpp>#include<opencv2/highgui.hpp>#include<vector>using namespace cv;using namespace std;void maxEntroy(Mat src,int&Threshold);int BasicGlobalThreshold(int *pg, int x, int y);int ThresholdOtsu(Mat src);int main() {Mat src,gray,dst1,dst2,dst3,dst4, dst5,dst6;src = imread("trees.png");cvtColor(src, gray, CV_BGR2GRAY);imshow("原图", src);imshow("灰度图", gray);///手动设置阈值threshold(gray, dst1,100, 255, CV_THRESH_BINARY);namedWindow("手动阈值",CV_WINDOW_AUTOSIZE);imshow("手动阈值", dst1);///自适应阈值计算图像领域平均灰度double max_value = 255;    int adpative_method = CV_ADAPTIVE_THRESH_GAUSSIAN_C;//CV_ADAPTIVE_THRESH_MEAN_C  int threshold_type = CV_THRESH_BINARY;int block_size = 21;//阈值的象素邻域大小  int offset = 3;//窗口尺寸  adaptiveThreshold(gray, dst2, max_value, adpative_method, threshold_type, block_size, offset);namedWindow("自适应阈值", CV_WINDOW_AUTOSIZE);imshow("自适应阈值", dst2);///最大熵法int Threshold3;maxEntroy(src, Threshold3);threshold(gray, dst3, Threshold3, 255, CV_THRESH_BINARY);namedWindow("最大熵阈值", CV_WINDOW_AUTOSIZE);imshow("最大熵阈值", dst3);///基本全局阈值法int Threshold4;Mat imgBasicGlobalThreshold = gray.clone();int pg[256], i;for (i = 0; i<256; i++) pg[i] = 0;for (int i= 0; i < gray.rows; i++){for (int j = 0; j < gray.cols; j++){pg[gray.at<uchar>(i,j)]++;//应该是无符号整型}}Threshold4 = BasicGlobalThreshold(pg, 0, 256); // 确定阈值  cout << "The Threshold of this Image in BasicGlobalThreshold is:" << Threshold4 << endl;//输出显示阀值  threshold(imgBasicGlobalThreshold, imgBasicGlobalThreshold, Threshold4, 255, CV_THRESH_BINARY); // 二值化   namedWindow("BasicGlobalThreshold", CV_WINDOW_AUTOSIZE);imshow("BasicGlobalThreshold", imgBasicGlobalThreshold);//显示图像  ///OTSU阈值Mat imgOTSU = gray.clone();int Threshold5;Threshold5 = ThresholdOtsu(imgOTSU);cout << "The Threshold of this Image in Otsu is:" << Threshold5 << endl;//输出显示阀值  threshold(imgOTSU, imgOTSU, Threshold5, 255, CV_THRESH_BINARY); // 二值化   namedWindow("imgOtsu", CV_WINDOW_AUTOSIZE);imshow("imgOtsu", imgOTSU);//显示图像   waitKey(0);}void maxEntroy(Mat src, int &Threshold) {int tbHist[256] = { 0 };                                        //每种像素个数int index = 0;                                                  //最大熵对应的灰度double Property = 0.0;                                          //像素所占概率double maxEntropy = -1.0;                                       //最大熵double frontEntropy = 0.0;                                      //前景熵double backEntropy = 0.0;                                       //背景熵//纳入计算的总像素数int TotalPixel = 0;int nCol = src.cols * src.channels();                           //每行的像素个数for (int i = 0; i < src.rows; i++){uchar* pData = src.ptr<uchar>(i);for (int j = 0; j < nCol; ++j){++TotalPixel;tbHist[pData[j]] += 1;}}for (int i = 0; i < 256; i++){//计算背景像素数double backTotal = 0;for (int j = 0; j < i; j++){backTotal += tbHist[j];}//背景熵for (int j = 0; j < i; j++){if (tbHist[j] != 0){Property = tbHist[j] / backTotal;backEntropy += -Property * logf((float)Property);}}//前景熵for (int k = i; k < 256; k++){if (tbHist[k] != 0){Property = tbHist[k] / (TotalPixel - backTotal);frontEntropy += -Property * logf((float)Property);}}if (frontEntropy + backEntropy > maxEntropy)    //得到最大熵{maxEntropy = frontEntropy + backEntropy;index = i;}//清空本次计算熵值frontEntropy = 0.0;backEntropy = 0.0;}Threshold = index;}int BasicGlobalThreshold(int *pg, int start, int end){int  i, t, t1, t2, k1, k2;double u, u1, u2;t = 0;u = 0;for (i = start; i<end; i++){t += pg[i];u += i*pg[i];}k2 = (int)(u / t);                          //  计算此范围灰度的平均值      do{k1 = k2;t1 = 0;u1 = 0;for (i = start; i <= k1; i++){             //  计算低灰度组的累加和  t1 += pg[i];u1 += i*pg[i];}t2 = t - t1;u2 = u - u1;if (t1)u1 = u1 / t1;                     //  计算低灰度组的平均值  elseu1 = 0;if (t2)u2 = u2 / t2;                     //  计算高灰度组的平均值  elseu2 = 0;k2 = (int)((u1 + u2) / 2);                 //  得到新的阈值估计值  } while (k1 != k2);                           //  数据未稳定,继续  return k1;                              //  返回阈值  }int ThresholdOtsu(Mat src){int height = src.cols;int width = src.rows;//histogramfloat histogram[256] = { 0 };for (int i = 0; i<src.rows; i++) {for (int j = 0; j<src.cols; j++) {histogram[src.at<uchar>(i,j)]++;}}//normalize histogramint size = height*width;for (int i = 0; i<256; i++) {histogram[i] = histogram[i] / size;}//average pixel valuefloat avgValue = 0;for (int i = 0; i<256; i++) {avgValue += i*histogram[i];}int threshold;float maxVariance = 0;float w = 0, u = 0;for (int i = 0; i<256; i++) {w += histogram[i];u += i*histogram[i];float t = avgValue*w - u;float variance = t*t / (w*(1 - w));if (variance>maxVariance) {maxVariance = variance;threshold = i;}}return threshold;}




0 0
原创粉丝点击