一、二值化
二值化是将一张单通道的图像中的像素分别设为0或者255 的操作,在数字图像处理的过程中这个一部分是很重要的,halcon 中有9个二值化的算子,每个用法都有各自的优势,这个等后面复习halcon 的时候再总结一下,然后和Opencv的二值化做一个对比,这里只说threshold和adaptiveThreshold算子
二、全局固定二值化-threshold
double threshold(
const Mat& src, // 必须是 8/32 位的图像
Mat& dst,
double thresh, // 手动输入的阈值0-255
double maxVal, // 最大阈值 一般都是255
int thresholdType // 这个是最重要的一个参数:阈值类型,有如下几个类型:
src(x,y) 表示原图的(x,y)点的像素值,thresh,手动输入的参数值,maxVal 最大值:
THRESH_BINARY:src(x,y)>thresh?maxVal:0;
THRESH_BINARY_INV:src(x,y)>thresh?0:maxVal;
THRESH_TRUNC: src(x,y)>thresh?thresh:src(x,y);(大于阈值=阈值,其他不变)
THRESH_TOZERO:src(x,y)>thresh?src(x,y):0;(大于阈值=原值,其他0)
THRESH_TOZERO_INV:src(x,y)>thresh?0:src(x,y);
THRESH_OTSU:不支持32位的,只支持8位的,非常适合有双峰的图像,
THRESH_TRIANGLE:不支持32位的,只支持8位的,适合单个波峰
)
代码显示如下:
int type_value = 2;
int type_Max = 5;
Mat src, src_gray, dest1, dest2;
int threshold_value = 127;
int threshold_max = 255;
const char* output_litle = "Binary_out_demo";
void Threshold_Demo(int, void*);
void Threshold_Demo(int, void*)
{
cvtColor(src, src_gray, CV_BGR2GRAY);
threshold(src_gray, dest1, threshold_value, threshold_max, type_value);
imshow(output_litle, dest1);
}
int main(int args, char* arg)
{
// point
src = imread("C:\\Users\\19473\\Desktop\\opencv_images\\88.jpg");
if (!src.data)
{
printf("could not load image....\n");
}
//1 显示灰色图像
namedWindow("input_demo", CV_WINDOW_AUTOSIZE);
namedWindow(output_litle, CV_WINDOW_AUTOSIZE);
imshow("input_demo", src);
createTrackbar("Threshold Value:", output_litle, &threshold_value, threshold_max, Threshold_Demo);
createTrackbar("Threshold Model:", output_litle, &type_value, type_Max, Threshold_Demo);
Threshold_Demo(0, 0);
waitKey(0);
return -1;
}
源码:
double threshold( InputArray _src,OutputArray _dst, double thresh, double maxval, int type )
{
Mat src = _src.getMat();
bool use_otsu = (type & THRESH_OTSU) != 0;
type &= THRESH_MASK;
if( use_otsu )
{
CV_Assert( src.type() == CV_8UC1 );
thresh = getThreshVal_Otsu_8u(src);
}
_dst.create( src.size(), src.type() );
Mat dst = _dst.getMat();
if( src.depth() == CV_8U )
{
int ithresh = cvFloor(thresh);
thresh = ithresh;
int imaxval = cvRound(maxval);
if( type == THRESH_TRUNC )
imaxval = ithresh;
imaxval = saturate_cast<uchar>(imaxval);
if( ithresh < 0 || ithresh >= 255 )
{
if( type == THRESH_BINARY || type == THRESH_BINARY_INV ||
((type == THRESH_TRUNC || type== THRESH_TOZERO_INV) && ithresh < 0) ||
(type == THRESH_TOZERO&& ithresh >= 255) )
{
int v = type ==THRESH_BINARY ? (ithresh >= 255 ? 0 : imaxval) :
type ==THRESH_BINARY_INV ? (ithresh >= 255 ? imaxval : 0) :
/*type == THRESH_TRUNC? imaxval :*/ 0;
dst.setTo(v);
}
else
src.copyTo(dst);
return thresh;
}
thresh = ithresh;
maxval = imaxval;
}
else if( src.depth() == CV_16S )
{
int ithresh = cvFloor(thresh);
thresh = ithresh;
int imaxval = cvRound(maxval);
if( type == THRESH_TRUNC )
imaxval = ithresh;
imaxval = saturate_cast<short>(imaxval);
if( ithresh < SHRT_MIN || ithresh >= SHRT_MAX )
{
if( type == THRESH_BINARY || type == THRESH_BINARY_INV ||
((type == THRESH_TRUNC || type== THRESH_TOZERO_INV) && ithresh < SHRT_MIN) ||
(type == THRESH_TOZERO&& ithresh >= SHRT_MAX) )
{
int v = type == THRESH_BINARY ?(ithresh >= SHRT_MAX ? 0 : imaxval) :
type == THRESH_BINARY_INV ?(ithresh >= SHRT_MAX ? imaxval : 0) :
/*type == THRESH_TRUNC ?imaxval :*/ 0;
dst.setTo(v);
}
else
src.copyTo(dst);
return thresh;
}
thresh = ithresh;
maxval = imaxval;
}
else if( src.depth() == CV_32F )
;
else
CV_Error( CV_StsUnsupportedFormat, "" );
parallel_for_(Range(0, dst.rows),
ThresholdRunner(src, dst,thresh, maxval, type),
dst.total()/(double)(1<<16));
return thresh;
}
三、局部自动阈值
adaptiveThreshold(
InputArray src, // 必须是8位的图像
OutputArray dst,
double local,// 局部的阈值,0-255
int adaptiveMethod, // 在邻域块中计算阈值用的方法,有两个:
ADAPTIVE_THRESH_MEAN_C:表示计算出领域的 平均值 -C(输入的第七个参数)
ADAPTIVE_THRESH_GAUSSIAN_C:表示计算出领域的 高斯均值 - C(输入的第七个参数)
int thresholdType, // 阈值类型,有两个类型:
THRESH_BINARY: src(x,y)>local?255:0;
THRESH_BINARY_INV :与THRESH_BINARY 相反
int blockSize, // 邻域块的大小,奇数
double C // 是一个偏移量
)
图像显示
代码显示
int block_size = 10;
int size_Max = 40;
Mat src, src_gray, dest1, dest2;
int local_threshold_value = 127;
int local_threshold_max = 255;
const char* output_litle = "Binary_out_demo";
void adaptiveThreshold_Demo(int, void*);
void adaptiveThreshold_Demo(int, void*)
{
cvtColor(src, src_gray, CV_BGR2GRAY);
src_gray.convertTo(src_gray, CV_8UC1);
int size_s = 2 * block_size + 1;
adaptiveThreshold(src_gray, dest1, local_threshold_value, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, size_s,10);
imshow(output_litle, dest1);
}
int main(int args, char* arg)
{
// point
src = imread("C:\\Users\\19473\\Desktop\\opencv_images\\88.jpg");
if (!src.data)
{
printf("could not load image....\n");
}
//1 显示灰色图像
namedWindow("input_demo", CV_WINDOW_AUTOSIZE);
namedWindow(output_litle, CV_WINDOW_AUTOSIZE);
imshow("input_demo", src);
createTrackbar("local Value:", output_litle, &local_threshold_value, 255, adaptiveThreshold_Demo);
createTrackbar("local Model:", output_litle, &block_size, size_Max, adaptiveThreshold_Demo);
adaptiveThreshold_Demo(0, 0);
waitKey(0);
return -1;
}
void adaptiveThreshold( InputArray _src, OutputArray _dst, double maxValue,
int method, int type, int blockSize, double delta )
{
Mat src = _src.getMat();
CV_Assert( src.type() == CV_8UC1 );
CV_Assert( blockSize % 2 == 1 && blockSize > 1 );
Size size = src.size();
_dst.create( size, src.type() );
Mat dst = _dst.getMat();
if( maxValue < 0 )
{
dst = Scalar(0);
return;
}
Mat mean;
if( src.data != dst.data )
mean = dst;
if( method == ADAPTIVE_THRESH_MEAN_C )
boxFilter( src, mean, src.type(), Size(blockSize, blockSize),
Point(-1,-1), true,BORDER_REPLICATE );
else if( method == ADAPTIVE_THRESH_GAUSSIAN_C )
GaussianBlur( src, mean, Size(blockSize, blockSize), 0, 0,BORDER_REPLICATE );
else
CV_Error( CV_StsBadFlag, "Unknown/unsupported adaptive thresholdmethod" );
int i, j;
uchar imaxval = saturate_cast<uchar>(maxValue);
int idelta = type == THRESH_BINARY ? cvCeil(delta) : cvFloor(delta);
uchar tab[768];
if( type == CV_THRESH_BINARY )
for( i = 0; i < 768; i++ )
tab[i] = (uchar)(i - 255 > -idelta ? imaxval : 0);
else if( type == CV_THRESH_BINARY_INV )
for( i = 0; i < 768; i++ )
tab[i] = (uchar)(i - 255 <= -idelta ? imaxval : 0);
else
CV_Error( CV_StsBadFlag, "Unknown/unsupported threshold type");
if( src.isContinuous() && mean.isContinuous() &&dst.isContinuous() )
{
size.width *= size.height;
size.height = 1;
}
for( i = 0; i < size.height; i++ )
{
const uchar* sdata = src.data + src.step*i;
const uchar* mdata = mean.data + mean.step*i;
uchar* ddata = dst.data + dst.step*i;
for( j = 0; j < size.width; j++ )
ddata[j] = tab[sdata[j] - mdata[j] + 255];
}
}
待续。。。。。。