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", 0);
    IplImage* dst = cvCreateImage(cvGetSize(img), 8, 1);
    int threshold = Otsu(img);
    printf("threshold = %d\n", threshold);
    cvThreshold(img, dst, threshold, 255, CV_THRESH_BINARY);

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


    cvWaitKey(-1);

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

    cvDestroyWindow("dst");
    return 0;
}



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

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

    //average pixel value    
    float 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];  //假设当前灰度i为阈值, 0~i 灰度的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例  
        u += i * histogram[i];  // 灰度i 之前的像素(0~i)的平均灰度值: 前景像素的平均灰度值  

        float t = avgValue * w - u;
        float variance = t * t / (w * (1 - 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[256] = { 0 };
    for (int i = 0; i<img.rows; i++)
    {
        const unsigned char* p = (const unsigned char*)img.ptr(i);
        for (int j = 0; j<img.cols; j++)
        {
            histogram[p[j]]++;
        }
    }

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

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

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

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

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

    int gray_threshold = 0;//阈值分割
    gray_threshold = otsu(gray);

    cout << gray_threshold << endl;
    Mat erzhitu;
    threshold(gray, erzhitu, gray_threshold, 255,1);
    namedWindow(window_name, WINDOW_AUTOSIZE);
    imshow(window_name, erzhitu);
Opencv中的分水岭算法(watershed algorithm)是一种自动图像分割算法,常用于分离图像中的前景和背景。下面是使用Opencv中的分水岭算法进行图像分割的步骤: 1. 读入图像并进行预处理,如去噪、灰度化等。 2. 对图像进行二值化处理,得到前景和背景的二值图像。 3. 对二值图像进行距离变换(distance transform),得到每个像素离最近的背景像素的距离。 4. 对距离变换后的图像进行阈值处理,得到图像的分水岭标记(watershed markers)。 5. 对分水岭标记进行修正,确保标记不会重叠或出现空洞。 6. 对分水岭标记应用分水岭算法,得到分割后的图像。 下面是使用Opencv实现分水岭算法的示例代码: ```python import cv2 import numpy as np # 读取图像并进行预处理 img = cv2.imread('input.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) # 进行距离变换 dist_transform = cv2.distanceTransform(thresh,cv2.DIST_L2,5) ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0) # 获取分水岭标记 sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(thresh,sure_fg) ret, markers = cv2.connectedComponents(sure_fg) markers = markers+1 markers[unknown==255] = 0 # 修正分水岭标记 markers = cv2.watershed(img,markers) img[markers == -1] = [255,0,0] # 显示分割结果 cv2.imshow('result', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这段代码中,我们首先读入一张图像并进行预处理,然后进行距离变换,得到每个像素到最近的背景像素的距离。接着使用阈值处理得到分水岭标记,修正分水岭标记并应用分水岭算法,最后显示分割结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值