gpt4 book ai didi

c++ - 如何选择阈值自动使用直方图的峰值?

转载 作者:太空宇宙 更新时间:2023-11-03 23:16:53 24 4
gpt4 key购买 nike

通过 OpenCV 库,我想对这样的图像进行阈值处理:

threshold(image, thresh, 220, 255, THRESH_BINARY_INV)

但是我想自动找到阈值(220)。

我使用 Otsu 来估计阈值。但它在我的情况下不起作用。

因此,我应该使用直方图峰值技术。我想在直方图中找到对应于图像背景和对象的两个峰值。它会自动设置两个峰值中间的阈值。我使用这本书(第 117 页和 496-505 页):Dwayne Phillips 的“C 图像处理”(http://homepages.inf.ed.ac.uk/rbf/BOOKS/PHILLIPS/)。我使用源代码在直方图中找到对应于图像背景和对象的两个峰值。这是我的形象:

enter image description here

这是我的 C++ 代码:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>

#include <iostream>
#include <stdio.h>
#include <fstream>

using namespace std;
using namespace cv;


int main()
{
Mat image0 = imread("C:/Users/Alireza/Desktop/contrast950318/2.bmp");
imshow("image0", image0);

Mat image, thresh, Tafrigh;
cvtColor(image0, image, CV_RGB2GRAY);


int N = image.rows*image.cols;

int histogram[256];

for (int i = 0; i < 256; i++) {
histogram[i] = 0;
}

//create histo
for (int i = 0; i < image.rows; i++){
for (int j = 0; j < image.cols; j++){
histogram[((int)image.at<uchar>(i, j))]++;
}
}


int peak1, peak2;
#define PEAKS 30
int distance[PEAKS], peaks[PEAKS][2];

int i, j = 0, max = 0, max_place = 0;

for (int i = 0; i<PEAKS; i++){
distance[i] = 0;
peaks[i][0] = -1;
peaks[i][1] = -1;
}

for (i = 0; i <= 255; i++){
max = histogram[i];
max_place = i;

//insert_into_peaks(peaks, max, max_place);
//int max, max_place, peaks[PEAKS][2];
//int i, j;
/* first case */
if (max > peaks[0][0]){
for (i = PEAKS - 1; i > 0; i--){
peaks[i][0] = peaks[i - 1][0];
peaks[i][1] = peaks[i - 1][1];
}
peaks[0][0] = max;
peaks[0][1] = max_place;
} /* ends if */

/* middle cases */
for (j = 0; j < PEAKS - 3; j++){
if (max < peaks[j][0] && max > peaks[j + 1][0]){
for (i = PEAKS - 1; i > j + 1; i--){
peaks[i][0] = peaks[i - 1][0];
peaks[i][1] = peaks[i - 1][1];
}

peaks[j + 1][0] = max;
peaks[j + 1][1] = max_place;
} /* ends if */
} /* ends loop over j */
/* last case */
if (max < peaks[PEAKS - 2][0] &&
max > peaks[PEAKS - 1][0]){
peaks[PEAKS - 1][0] = max;
peaks[PEAKS - 1][1] = max_place;
} /* ends if */

}/* ends loop over i */



for (int i = 1; i<PEAKS; i++){
distance[i] = peaks[0][1] - peaks[i][1];
if (distance[i] < 0)
distance[i] = distance[i] * (-1);
}

peak1 = peaks[0][1];
cout << " peak1= " << peak1;

for (int i = PEAKS - 1; i > 0; i--){
if (distance[i] > 1)
peak2 = peaks[i][1];

}
cout << " peak2= " << peak2;


int mid_point;
//int peak1, peak2;
short hi, low;

unsigned long sum1 = 0, sum2 = 0;
if (peak1 > peak2)
mid_point = ((peak1 - peak2) / 2) + peak2;
if (peak1 < peak2)
mid_point = ((peak2 - peak1) / 2) + peak1;

for (int i = 0; i<mid_point; i++)
sum1 = sum1 + histogram[i];
for (int i = mid_point; i <= 255; i++)
sum2 = sum2 + histogram[i];
if (sum1 >= sum2){
low = mid_point;
hi = 255;
}
else{
low = 0;
hi = mid_point;
}

cout << " low= " << low << " hi= " << hi;



double threshnum = 0.5* (low + hi);
threshold(image, thresh, threshnum, hi, THRESH_BINARY_INV);


waitKey(0);
return 0;
}

但我不知道这段代码是否正确。如果正确,为什么阈值是202?

对于如何解决这个任务,您有什么建议?或者我可以在互联网上的哪些资源上找到帮助?

最佳答案

您也可以使用最大熵。在某些情况下,仅使用熵的高频可能会更好

int maxentropie(const cv::Mat1b& src)
{
// Histogram
cv::Mat1d hist(1, 256, 0.0);
for (int r=0; r<src.rows; ++r)
for (int c=0; c<src.cols; ++c)
hist(src(r,c))++;

// Normalize
hist /= double(src.rows * src.cols);

// Cumulative histogram
cv::Mat1d cumhist(1, 256, 0.0);
float sum = 0;
for (int i = 0; i < 256; ++i)
{
sum += hist(i);
cumhist(i) = sum;
}

cv::Mat1d hl(1, 256, 0.0);
cv::Mat1d hh(1, 256, 0.0);

for (int t = 0; t < 256; ++t)
{
// low range entropy
double cl = cumhist(t);
if (cl > 0)
{
for (int i = 0; i <= t; ++i)
{
if (hist(i) > 0)
{
hl(t) = hl(t) - (hist(i) / cl) * log(hist(i) / cl);
}
}
}

// high range entropy
double ch = 1.0 - cl; // constraint cl + ch = 1
if (ch > 0)
{
for (int i = t+1; i < 256; ++i)
{
if (hist(i) > 0)
{
hh(t) = hh(t) - (hist(i) / ch) * log(hist(i) / ch);
}
}
}
}

// choose best threshold

cv::Mat1d entropie(1, 256, 0.0);
double h_max = hl(0) + hh(0);
int threshold = 0;
entropie(0) = h_max;

for (int t = 1; t < 256; ++t)
{
entropie(t) = hl(t) + hh(t);
if (entropie(t) > h_max)
{
h_max = entropie(t);
threshold = uchar(t);
}
}
if(threshold==0) threshold=255;
return threshold;
}

关于c++ - 如何选择阈值自动使用直方图的峰值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37707535/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com