19,468
社区成员
发帖
与我相关
我的任务
分享
随笔 - 96 文章 - 0 评论 - 44
【20160924】GOCVHelper 图像增强部分(1)
图像增强是图像处理的第一步。这里集成了一些实际使用过程中有用的函数。
//读取灰度或彩色图片到灰度
Mat imread2gray(string path){
Mat src = imread(path);
Mat srcClone = src.clone();
if (CV_8UC3 == srcClone.type() )
cvtColor(srcClone,srcClone,CV_BGR2GRAY);
return srcClone;
}
算法核心在于判断读入图片的通道数,如果是灰度图片则保持;如果是彩色图片则转换为灰度图片。通过这样一个函数,就能够直接获得灰度图片。
//带有上下限的threshold
Mat threshold2(Mat src,int minvalue,int maxvalue){
Mat thresh1;
Mat thresh2;
Mat dst;
threshold(src,thresh1,minvalue,255, THRESH_BINARY);
threshold(src,thresh2,maxvalue,255,THRESH_BINARY_INV);
dst = thresh1 & thresh2;
return dst;
}
Opencv提供的threshold算法很强大,但是只能够取单门限。这里修改成可以取双门限的形式。
//自适应门限的canny算法
//canny2
Mat canny2(Mat src){
Mat imagetmp = src.clone();
double low_thresh = 0.0;
double high_thresh = 0.0;
AdaptiveFindThreshold(imagetmp,&low_thresh,&high_thresh);
Canny(imagetmp,imagetmp,low_thresh,high_thresh);
return imagetmp;}
void AdaptiveFindThreshold( Mat src,double *low,double *high,int aperture_size){
const int cn = src.channels();
Mat dx(src.rows,src.cols,CV_16SC(cn));
Mat dy(src.rows,src.cols,CV_16SC(cn));
Sobel(src,dx,CV_16S,1,0,aperture_size,1,0,BORDER_REPLICATE);
Sobel(src,dy,CV_16S,0,1,aperture_size,1,0,BORDER_REPLICATE);
CvMat _dx = dx;
CvMat _dy = dy;
_AdaptiveFindThreshold(&_dx, &_dy, low, high); }
void _AdaptiveFindThreshold(CvMat *dx, CvMat *dy, double *low, double *high){
CvSize size;
IplImage *imge=0;
int i,j;
CvHistogram *hist;
int hist_size = 255;
float range_0[]={0,256};
float* ranges[] = { range_0 };
double PercentOfPixelsNotEdges = 0.7;
size = cvGetSize(dx);
imge = cvCreateImage(size, IPL_DEPTH_32F, 1);
// 计算边缘的强度, 并存于图像中
float maxv = 0;
for(i = 0; i < size.height; i++ ){
const short* _dx = (short*)(dx->data.ptr + dx->step*i);
const short* _dy = (short*)(dy->data.ptr + dy->step*i);
float* _image = (float *)(imge->imageData + imge->widthStep*i);
for(j = 0; j < size.width; j++){
_image[j] = (float)(abs(_dx[j]) + abs(_dy[j]));
maxv = maxv < _image[j] ? _image[j]: maxv;}}
if(maxv == 0){
*high = 0;
*low = 0;
cvReleaseImage( &imge );
return;}
// 计算直方图
range_0[1] = maxv;
hist_size = (int)(hist_size > maxv ? maxv:hist_size);
hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
cvCalcHist( &imge, hist, 0, NULL );
int total = (int)(size.height * size.width * PercentOfPixelsNotEdges);
float sum=0;
int icount = hist->mat.dim[0].size;
float *h = (float*)cvPtr1D( hist->bins, 0 );
for(i = 0; i < icount; i++){
sum += h[i];
if( sum > total )
break; }
// 计算高低门限
*high = (i+1) * maxv / hist_size ;
*low = *high * 0.4;
cvReleaseImage( &imge );
cvReleaseHist(&hist); }
// end of canny2
我们在使用Opencv的canny算法的时候,一般是按照经验填写上下门限值。为了解决这个问题,通过自适应算法(算法来源我想不起来了),自动计算出上下门限。能够取得不错效果。
来自为知笔记(Wiz)
随笔 - 96 文章 - 0 评论 - 44
【20160924】GOCVHelper MFC增强算法(1)
//递归读取目录下全部文件(flag为r的时候递归)
void getFiles(string path, vector<string>& files,string flag){
//文件句柄
long hFile = 0;
//文件信息
struct _finddata_t fileinfo;
string p;
if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) != -1){
do{
//如果是目录,迭代之,如果不是,加入列表
if((fileinfo.attrib & _A_SUBDIR)){
if(strcmp(fileinfo.name,".") != 0 && strcmp(fileinfo.name,"..") != 0 && flag=="r")
getFiles( p.assign(path).append("\\").append(fileinfo.name), files,flag );
}
else{
files.push_back(p.assign(path).append("\\").append(fileinfo.name) );
}
}while(_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}
//递归读取目录下全部图片
void getFiles(string path, vector<Mat>& files,string flag){
vector<string> fileNames;
getFiles(path,fileNames,flag);
for (int i=0;i<fileNames.size();i++){
Mat tmp = imread(fileNames[i]);
if (tmp.rows>0)//如果是图片
files.push_back(tmp);
}
}
//递归读取目录下全部图片和名称
void getFiles(string path, vector<pair<Mat,string>>& files,string flag){
vector<string> fileNames;
getFiles(path,fileNames,flag);
for (int i=0;i<fileNames.size();i++){
Mat tmp = imread(fileNames[i]);
if (tmp.rows>0){
pair<Mat,string> apir;
apir.first = tmp;
apir.second = fileNames[i];
files.push_back(apir);
}
}
}
在结合MFC的程序设计中,经常涉及到图片文件输入输出的情况。所以我编写集成了一些算法,在这个方面进行增强。getFiles函数能够递归地读取某个目录下面所有文件的据对路径。这样就能够一次性获得所有的图片;对getFiles进行重载,这样能够直接将图片读入mat,或者读入pair<Mat,string>,更加方便。
可能你会问,既然已经读入Mat了,但是为什么还要读出pair<Mat,string>了?这是因为很多时候在获得图片的时候还需要获得图片的名称。
////删除目录下的全部文件
void deleteFiles(string path,string flag){
//文件句柄
long hFile = 0;
//文件信息
struct _finddata_t fileinfo;
string p;
if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) != -1){
do{
//如果是目录,迭代之,如果不是,加入列表
if((fileinfo.attrib & _A_SUBDIR)){
if(strcmp(fileinfo.name,".") != 0 && strcmp(fileinfo.name,"..") != 0 && flag=="r")
deleteFiles(p.assign(path).append("\\").append(fileinfo.name).c_str(),flag );
}
else{
deleteFiles(p.assign(path).append("\\").append(fileinfo.name).c_str());
}
}while(_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}
删除目录下的全部文件。
来自为知笔记(Wiz)
贴点楼主代码,谢谢分享