天天看點

opencv——最大門檻值分割

opencv1.0版本

#include "stdio.h"  
#include "cv.h"  
#include "highgui.h"  
#include "Math.h"
int Otsu(IplImage* src);


int main(int argc, char*argv[])
{
    IplImage* img = cvLoadImage("D:\\chengxu\\opencv\\Desert.jpg", );
    IplImage* dst = cvCreateImage(cvGetSize(img), , );
    int threshold = Otsu(img);
    printf("threshold = %d\n", threshold);
    cvThreshold(img, dst, threshold, , CV_THRESH_BINARY);

    cvNamedWindow("img", );
    cvShowImage("img", dst);


    cvWaitKey(-);

    cvReleaseImage(&img);
    cvReleaseImage(&dst);

    cvDestroyWindow("dst");
    return ;
}



int Otsu(IplImage* src)
{
    int height = src->height;
    int width = src->width;

    //histogram    
    float histogram[] = {  };
    for (int i = ; i < height; i++)
    {
        unsigned char* p = (unsigned char*)src->imageData + src->widthStep * i;
        for (int j = ; j < width; j++)
        {
            histogram[*p++]++;
        }
    }
    //normalize histogram    
    int size = height * width;
    for (int i = ; i < ; i++)
    {
        histogram[i] = histogram[i] / size;
    }

    //average pixel value    
    float avgValue = ;
    for (int i = ; i < ; i++)
    {
        avgValue += i * histogram[i];  //整幅圖像的平均灰階  
    }

    int threshold;
    float maxVariance = ;
    float w = , u = ;
    for (int i = ; i < ; i++)
    {
        w += histogram[i];  //假設目前灰階i為門檻值, 0~i 灰階的像素(假設像素值在此範圍的像素叫做前景像素) 所占整幅圖像的比例  
        u += i * histogram[i];  // 灰階i 之前的像素(0~i)的平均灰階值: 前景像素的平均灰階值  

        float t = avgValue * w - u;
        float variance = t * t / (w * ( - w));
        if (variance > maxVariance)
        {
            maxVariance = variance;
            threshold = i;
        }
    }

    return threshold;
}
           

opencv2.0版本

#include<opencv2/opencv.hpp>
#include"cv.h"
#include"highgui.h"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;
using namespace std;

int otsu(const Mat &img)//最大類間方差門檻值分割
{
    float histogram[] = {  };
    for (int i = ; i<img.rows; i++)
    {
        const unsigned char* p = (const unsigned char*)img.ptr(i);
        for (int j = ; j<img.cols; j++)
        {
            histogram[p[j]]++;
        }
    }

    float avgValue = ;
    int numPixel = img.cols*img.rows;
    for (int i = ; i<; i++)
    {
        histogram[i] = histogram[i] / numPixel;
        avgValue += i*histogram[i];
    }

    int threshold = ;
    float gmax = ;
    float wk = , uk = ;
    for (int i = ; i<; i++) {

        wk += histogram[i];
        uk += i*histogram[i];

        float ut = avgValue*wk - uk;
        float g = ut*ut / (wk*( - wk));

        if (g > gmax)
        {
            gmax = g;
            threshold = i;
        }
    }
    return threshold;
}
int main( int, char** argv )
{
    Mat src,gray;
    int width = ;
    int height = ;
    int channels = ;
    const char* window_name = "erzhitu";
    src = imread("C:\\Program Files (x86)\\MesaImaging\\Swissranger\\matlab\\swissranger\\xx.jpg");
    if (src.empty())
    {
        return -;
    }
    width = src.cols;//求圖像的行列及通道
    height = src.rows;
    channels = src.channels();
    cvtColor(new_src, gray, CV_BGR2GRAY);//灰階化

    int gray_threshold = ;//門檻值分割
    gray_threshold = otsu(gray);

    cout << gray_threshold << endl;
    Mat erzhitu;
    threshold(gray, erzhitu, gray_threshold, ,);
    namedWindow(window_name, WINDOW_AUTOSIZE);
    imshow(window_name, erzhitu);