我想实现一个局部阈值算法,我需要你的专业知识。
我的图像被调整为600x400,灰度。
关于本地化的基本思维过程:
- if the center pixel of the mask is above 50% of the maximum intensity, set the center pixel true.(apply mask)
我的问题是:
发布于 2015-01-15 22:43:45
经过进一步的思考,并找到了如何在编程中使用我的基本知识,我想出了这段代码,它不是最有效的,而是完成了工作。
我的方法的主要问题是什么?
我解决那件事的方法是什么?
结果:
代码:
double maxVal, minVal;
cv::Mat output;
int top, bottom, left , right;
int borderType = cv::BORDER_CONSTANT;
cv::Scalar value;
top = (int) (4); bottom = (int) (4);
left = (int) (4); right = (int) (4);
output = src;
out = src;
value = 0;
cv::copyMakeBorder(src,output,top,bottom,left,right,borderType,value);
for(int y = 4; y < output.rows - 4; y++) {
for(int x = 4; x < output.cols - 4; x ++) {
// apply local ROI
cv::Mat ROI = output(cv::Rect(cv::Point(x-4,y-4),cv::Size(9,9)));
cv::minMaxLoc(ROI,&minVal,&maxVal); // extract max intensity values in the ROI
if(src.at<uchar>(cv::Point(x-4,y-4)) >= 0.5*maxVal){ // apply local threshold w.r.t highest intensity level
out.at<uchar>(cv::Point(x-4,y-4)) = 255; // change pixel value in mask if true
}else{
out.at<uchar>(cv::Point(x-4,y-4)) = 0;
}
}
}
}它需要一些清理,我知道,但希望这将有助于其他人得到一些想法。
发布于 2015-01-15 07:19:52
您可以通过扩展,然后在OpenCV中进行比较来做到这一点;
im = load image here;
di = dilate im with a 9x9 kernel;
bw = im > (di * 0.5); // in OpenCV, pixels of bw are set to 255 or 0用Matlab/Octave中的4x6图像和3x3内核来说明这一点的一个简单例子:
林=
1 2 3 4 5 6
2 3 4 5 6 7
3 4 5 6 7 8
4 5 6 7 8 9迪=
3 4 5 6 7 7
4 5 6 7 8 8
5 6 7 8 9 9
5 6 7 8 9 9th = di * .5
th =
1.5000 2.0000 2.5000 3.0000 3.5000 3.5000
2.0000 2.5000 3.0000 3.5000 4.0000 4.0000
2.5000 3.0000 3.5000 4.0000 4.5000 4.5000
2.5000 3.0000 3.5000 4.0000 4.5000 4.5000bw = im > th
bw =
0 0 1 1 1 1
0 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1发布于 2015-01-14 22:55:13
我恐怕这种做法并不完全正确。让我解释一下:对于涉及内核的操作,必须小心地将放在要转换的像素上的内核的中心。那是因为3x3,5x5,7x7,9x9 (.)内核只计算图像中的(一个像素)的值,这个值位于内核的中心0,0。
如果您考虑如何计算图像的第一个像素的值,9x9内核的中心将放置在坐标0,0上。这意味着内核的3/4将放置在负坐标,即指不存在的像素的坐标:
[-4,-4][-3,-4][-2,-4][-1,-4][ 0,-4][ 1,-4][ 2,-4][ 3,-4][ 4,-4]
[-4,-3][-3,-3][-2,-3][-1,-3][ 0,-3][ 1,-3][ 2,-3][ 3,-3][ 4,-3]
[-4,-2][-3,-2][-2,-2][-1,-2][ 0,-2][ 1,-2][ 2,-2][ 3,-2][ 4,-2]
[-4,-1][-3,-1][-2,-1][-1,-1][ 0,-1][ 1,-1][ 2,-1][ 3,-1][ 4,-1]
[-4, 0][-3, 0][-2, 0][-1, 0][ 0, 0][ 1, 0][ 2, 0][ 3, 0][ 4, 0]
[-4, 1][-3, 1][-2, 1][-1, 1][ 0, 1][ 1, 1][ 2, 1][ 3, 1][ 4, 1]
[-4, 2][-3, 2][-2, 2][-1, 2][ 0, 2][ 1, 2][ 2, 2][ 3, 2][ 4, 2]
[-4, 3][-3, 3][-2, 3][-1, 3][ 0, 3][ 1, 3][ 2, 3][ 3, 3][ 4, 3]
[-4, 4][-3, 4][-2, 4][-1, 4][ 0, 4][ 1, 4][ 2, 4][ 3, 4][ 4, 4]--这总是发生在靠近图像边界的像素上。因此,对于第一个像素的计算,我们必须将计算限制在内核的1/4,这是指目标图像中的有效坐标:
[ ][ ][ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ 0, 0][ 1, 0][ 2, 0][ 3, 0][ 4, 0]
[ ][ ][ ][ ][ 0, 1][ 1, 1][ 2, 1][ 3, 1][ 4, 1]
[ ][ ][ ][ ][ 0, 2][ 1, 2][ 2, 2][ 3, 2][ 4, 2]
[ ][ ][ ][ ][ 0, 3][ 1, 3][ 2, 3][ 3, 3][ 4, 3]
[ ][ ][ ][ ][ 0, 4][ 1, 4][ 2, 4][ 3, 4][ 4, 4]因此,当前方法的问题是,在某个时候,您将设置一个具有负坐标的ROI,当执行这些指令时,您将看到一个很好的崩溃:
cv::Mat ROI_Mat = input(ROI); // crash 解决方案是不使用ROI,只需自己实现该算法。我只是无法看到这种自定义计算与cv::filter2D()一起工作。以下是一些帮助你开始工作的小东西:
void local_threshold(const cv::Mat& input, cv::Mat& output)
{
if (input.channels() != 1)
{
std::cout << "local_threshold !!! input image must be single channel" << std::endl;
return;
}
output = cv::Mat(input.rows, input.cols, CV_8UC1);
double min_val = 0, max_val = 0;
for (int i = 0; i < input.rows; i++)
for (int j = 0; j < input.cols; j++)
{
cv::Mat kernel = Mat::zeros(9, 9, output.type());
// Implement logic to fill the 9x9 kernel with
// values from the input Mat, respecting boundaries.
cv::Scalar avg_intensity = cv::mean(kernel);
cv::minMaxLoc(kernel, &min_val,&max_val);
if (input.at<uchar>(i,j) > (max_val / 2))
output.at<unsigned char>(i,j) = 255;
else
output.at<unsigned char>(i,j) = 0;
}
}https://stackoverflow.com/questions/27948473
复制相似问题