GOCVHelper(GreenOpen Computer Version Helper )是我在這幾年編寫圖像處理程序的過程中積累下來的函數庫。主要是對Opencv的適當擴展和在實現Mfc程序時候的功能增強。
//名稱:GOCVHelper0.7b.cpp //功能:圖像處理和MFC增強 //作者:jsxyhelu([email protected] http://jsxyhelu.cnblogs.com) //組織:GREENOPEN //日期:2016-09-24 #include "stdafx.h" #include <windows.h> #include <iostream> #include <fstream> #include <cstdlib> #include <io.h> #include <stdlib.h> #include <stdio.h> #include <vector> #include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace std; using namespace cv; #define VP vector<cv::Point> //用VP符號代替 vector<point> #define DIRECTION_X 0 #define DIRECTION_Y 1 //調用算法庫請在Opencv和Mfc正確配置的環境下。 //並且配置 項目-屬性-配置屬性-常規-字符集 設置爲 使用多字節字符集 //和 項目-屬性-配置屬性-c/c++-預處理器-預處理器定義 加入 _CRT_SECURE_NO_WARNINGS namespace GO{ //讀取灰度或彩色圖片到灰度 Mat imread2gray(string path); //帶有上下限的threshold Mat threshold2(Mat src,int minvalue,int maxvalue); //自適應門限的canny算法 Mat canny2(Mat src); void AdaptiveFindThreshold( Mat src,double *low,double *high,int aperture_size=3); void _AdaptiveFindThreshold(CvMat *dx, CvMat *dy, double *low, double *high); //填充孔洞 Mat fillHoles(Mat src); float getWhiteRate(Mat src); Mat getInnerHoles(Mat src); //頂帽去光差,radius爲模板半徑 Mat moveLightDiff(Mat src,int radius = 40); //將 DEPTH_8U型二值圖像進行細化 經典的Zhang並行快速細化算法 void thin(const Mat &src, Mat &dst, const int iterations=100); //使得rect區域半透明 Mat translucence(Mat src,Rect rect,int idepth = 90); //使得rect區域打上馬賽克 Mat mosaic(Mat src,Rect rect,int W = 18,int H = 18); //----------------------------------------------------------------------------------------------------------------------------------------// //尋找最大的輪廓 VP FindBigestContour(Mat src); //尋找並繪製出彩色聯通區域 vector<VP> connection2(Mat src,Mat& draw); vector<VP> connection2(Mat src); //根據輪廓的面積大小進行選擇 vector<VP> selectShapeArea(Mat src,Mat& draw,vector<VP> contours,int minvalue,int maxvalue); vector<VP> selectShapeArea(vector<VP> contours,int minvalue,int maxvalue); //根據輪廓的圓的特性進行選擇 vector<VP> selectShapeArea(Mat src,Mat& draw,vector<VP> contours,int minvalue,int maxvalue); vector<VP> selectShapeArea(vector<VP> contours,int minvalue,int maxvalue); //計算輪廓的圓的特性 float calculateCircularity(VP contour); //返回兩點之間的距離 float getDistance(Point2f f1,Point2f f2); //----------------------------------------------------------------------------------------------------------------------------------------// //投影到x或Y軸上,上波形爲vup,下波形爲vdown,gap爲誤差間隔 void projection2(Mat src,vector<int>& vup,vector<int>& vdown,int direction = DIRECTION_X,int gap = 10); //----------------------------------------------------------------------------------------------------------------------------------------// //遞歸讀取目錄下全部文件 void getFiles(string path, vector<string>& files,string flag ="r"/*如果不想遞歸這裏不寫r就可以*/); //遞歸讀取目錄下全部圖片 void getFiles(string path, vector<Mat>& files,string flag = "r"); //遞歸讀取目錄下全部圖片和名稱 void getFiles(string path, vector<pair<Mat,string>>& files,string flag="r"); //刪除目錄下的全部文件 void deleteFiles(string path,string flag = "r"); //創建或續寫目錄下的csv文件,填寫“文件位置-分類”對 int writeCsv(const string& filename,const Vector<pair<string,string>>srcVect,char separator=';'); //讀取目錄下的csv文件,獲得“文件位置-分類”對 vector<pair<string,string>> readCsv(const string& filename, char separator = ';') ; //----------------------------------------------------------------------------------------------------------------------------------------// //C++的spilt函數 void SplitString(const string& s, vector<string>& v, const string& c); //! 通過文件夾名稱獲取文件名,不包括後綴 void getFileName(const string& filepath, string& name,string& lastname); //-----------------------------------------------------------------------------------------------------------------------------------------// //ini 操作 CString GetInitString( CString Name1 ,CString Name2); void WriteInitString( CString Name1 ,CString Name2 ,CString strvalue); //excel操作 CString ExportListToExcel(CString sExcelFile,CListCtrl* pList, CString strTitle); BOOL GetDefaultXlsFileName(CString& sExcelFile); }
一、圖像處理部分
增強後的圖像需要通過圖像處理獲得定量的值。在實際程序設計過程中,輪廓很多時候都是重要的分析變量。參考Halcon的相關函數,我增強了Opencv在這塊的相關功能。
//尋找最大的輪廓 VP FindBigestContour(Mat src){ int imax = 0; //代表最大輪廓的序號 int imaxcontour = -1; //代表最大輪廓的大小 std::vector<std::vector<cv::Point>>contours; findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE); for (int i=0;i<contours.size();i++){ int itmp = contourArea(contours[i]);//這裏採用的是輪廓大小 if (imaxcontour < itmp ){ imax = i; imaxcontour = itmp; } } return contours[imax]; }
就是直接返回最大的輪廓。
//尋找並繪製出彩色聯通區域 vector<VP> connection2(Mat src,Mat& draw){ draw = Mat::zeros(src.rows,src.cols,CV_8UC3); vector<VP>contours; findContours(src.clone(),contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE); //由於給大的區域着色會覆蓋小的區域,所以首先進行排序操作 //冒泡排序,由小到大排序 VP vptmp; for(int i=1;i<contours.size();i++){ for(int j=contours.size()-1;j>=i;j--){ if(contours[j].size()<contours[j-1].size()){ vptmp = contours[j-1]; contours[j-1] = contours[j]; contours[j] = vptmp; } } } //打印結果 for (int i=contours.size()-1;i>=0;i--){ Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)); drawContours(draw,contours,i,color,-1); } return contours; } vector<VP> connection2(Mat src){ Mat draw; return connection2(src,draw); }
//根據輪廓的面積大小進行選擇 vector<VP> selectShapeArea(Mat src,Mat& draw,vector<VP> contours,int minvalue,int maxvalue){ vector<VP> result_contours; draw = Mat::zeros(src.rows,src.cols,CV_8UC3); for (int i=0;i<contours.size();i++){ double countour_area = contourArea(contours[i]); if (countour_area >minvalue && countour_area<maxvalue) result_contours.push_back(contours[i]); } for (int i=0;i<result_contours.size();i++){ int iRandB = rng.uniform(0,255); int iRandG = rng.uniform(0,255); int iRandR = rng.uniform(0,255); Scalar color = Scalar(iRandB,iRandG,iRandR); drawContours(draw,result_contours,i,color,-1); char cbuf[100];sprintf_s(cbuf,"%d",i+1); //尋找最小覆蓋圓,求出圓心。使用反色打印輪廓序號 float radius; cv::Point2f center; cv::minEnclosingCircle(result_contours[i],center,radius); putText(draw,cbuf,center, FONT_HERSHEY_PLAIN ,5,Scalar(255-iRandB,255-iRandG,255-iRandR),5); } return result_contours; } vector<VP> selectShapeArea(vector<VP> contours,int minvalue,int maxvalue) { vector<VP> result_contours; for (int i=0;i<contours.size();i++){ double countour_area = contourArea(contours[i]); if (countour_area >minvalue && countour_area<maxvalue) result_contours.push_back(contours[i]); } return result_contours; }
//根據輪廓的圓的特性進行選擇 vector<VP> selectShapeCircularity(Mat src,Mat& draw,vector<VP> contours,float minvalue,float maxvalue){ vector<VP> result_contours; draw = Mat::zeros(src.rows,src.cols,CV_8UC3); for (int i=0;i<contours.size();i++){ float fcompare = calculateCircularity(contours[i]); if (fcompare >=minvalue && fcompare <=maxvalue) result_contours.push_back(contours[i]); } for (int i=0;i<result_contours.size();i++){ Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)); drawContours(draw,result_contours,i,color,-1); } return result_contours; } vector<VP> selectShapeCircularity(vector<VP> contours,float minvalue,float maxvalue){ vector<VP> result_contours; for (int i=0;i<contours.size();i++){ float fcompare = calculateCircularity(contours[i]); if (fcompare >=minvalue && fcompare <=maxvalue) result_contours.push_back(contours[i]); } return result_contours; } //計算輪廓的圓的特性 float calculateCircularity(VP contour){ Point2f center; float radius = 0; minEnclosingCircle((Mat)contour,center,radius); //以最小外接圓半徑作爲數學期望,計算輪廓上各點到圓心距離的標準差 float fsum = 0; float fcompare = 0; for (int i=0;i<contour.size();i++){ Point2f ptmp = contour[i]; float fdistenct = sqrt((float)((ptmp.x - center.x)*(ptmp.x - center.x)+(ptmp.y - center.y)*(ptmp.y-center.y))); float fdiff = abs(fdistenct - radius); fsum = fsum + fdiff; } fcompare = fsum/(float)contour.size(); return fcompare; } //返回兩點之間的距離 float getDistance(Point2f f1,Point2f f2) { return sqrt((float)(f1.x - f2.x)*(f1.x - f2.x) + (f1.y -f2.y)*(f1.y- f2.y)); }
基於Opencv論壇上提供的關於圓的尺度的評判算法,編寫Opencv的圓的特性判斷算法。主要就是“ 以最小外接圓半徑作爲數學期望,計算輪廓上各點到圓心距離的標準差 ”這個標準差達到一定的範圍,則可以認定輪廓是爲圓形的。
//投影到x或Y軸上,上波形爲vup,下波形爲vdown,gap爲誤差間隔 void projection2(Mat src,vector<int>& vup,vector<int>& vdown,int direction,int gap){ Mat tmp = src.clone(); vector<int> vdate; if (DIRECTION_X == direction){ for (int i=0;i<tmp.cols;i++){ Mat data = tmp.col(i); int itmp = countNonZero(data); vdate.push_back(itmp); } }else{ for (int i=0;i<tmp.rows;i++){ Mat data = tmp.row(i); int itmp = countNonZero(data); vdate.push_back(itmp); } } //整形,去除長度小於gap的零的空洞 if (vdate.size()<=gap) return; for (int i=0;i<vdate.size()-gap;i++){ if (vdate[i]>0 && vdate[i+gap]>0){ for (int j=i;j<i+gap;j++){ vdate[j] = 1; } i = i+gap-1; } } //記錄上下沿 for (int i=1;i<vdate.size();i++){ if (vdate[i-1] == 0 && vdate[i]>0) vup.push_back(i); if (vdate[i-1]>0 && vdate[i] == 0) vdown.push_back(i); } }
投影變換。投影分析是非常重要的分析方式。這裏的投影分析是從書上扒下來的,能夠直接對圖像進行投影分析,效果非常好。當然工具具備了,如何靈活使用也是需要經驗的。
二、圖像增強部分
圖像增強是圖像處理的第一步。這裏集成了一些實際使用過程中有用的函數。
//讀取灰度或彩色圖片到灰度 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; }
//自適應門限的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算法的時候,一般是按照經驗填寫上下門限值。爲了解決這個問題,通過自適應算法,自動計算出上下門限。能夠取得不錯效果。
//填充孔洞 //fillholes Mat fillHoles(Mat src){ Mat dst = getInnerHoles(src); threshold(dst,dst,0,255,THRESH_BINARY_INV); dst = src + dst; return dst; } //獲得圖像中白色的比率 float getWhiteRate(Mat src){ int iWhiteSum = 0; for (int x =0;x<src.rows;x++){ for (int y=0;y<src.cols;y++){ if (src.at<uchar>(x,y) != 0) iWhiteSum = iWhiteSum +1; } } return (float)iWhiteSum/(float)(src.rows*src.cols); } //獲得內部孔洞圖像 Mat getInnerHoles(Mat src){ Mat clone = src.clone(); srand((unsigned)time(NULL)); // 生成時間種子 float fPreRate = getWhiteRate(clone); float fAftRate = 0; do { clone = src.clone(); // x y 對於 cols rows floodFill(clone,Point((int)rand()%src.cols,(int)rand()%src.rows),Scalar(255)); fAftRate = getWhiteRate(clone); } while ( fAftRate < 0.6); return clone; } // end of fillHoles
//頂帽去光差,radius爲模板半徑 Mat moveLightDiff(Mat src,int radius){ Mat dst; Mat srcclone = src.clone(); Mat mask = Mat::zeros(radius*2,radius*2,CV_8U); circle(mask,Point(radius,radius),radius,Scalar(255),-1); //頂帽 erode(srcclone,srcclone,mask); dilate(srcclone,srcclone,mask); dst = src - srcclone; return dst;}
//將 DEPTH_8U型二值圖像進行細化 經典的Zhang並行快速細化算法 //細化算法 void thin(const Mat &src, Mat &dst, const int iterations){ const int height =src.rows -1; const int width =src.cols -1; //拷貝一個數組給另一個數組 if(src.data != dst.data) src.copyTo(dst); int n = 0,i = 0,j = 0; Mat tmpImg; uchar *pU, *pC, *pD; bool isFinished =FALSE; for(n=0; n<iterations; n++){ dst.copyTo(tmpImg); isFinished =FALSE; //一次 先行後列掃描 開始 //掃描過程一 開始 for(i=1; i<height; i++) { pU = tmpImg.ptr<uchar>(i-1); pC = tmpImg.ptr<uchar>(i); pD = tmpImg.ptr<uchar>(i+1); for(int j=1; j<width; j++){ if(pC[j] > 0){ int ap=0; int p2 = (pU[j] >0); int p3 = (pU[j+1] >0); if (p2==0 && p3==1) ap++; int p4 = (pC[j+1] >0); if(p3==0 && p4==1) ap++; int p5 = (pD[j+1] >0); if(p4==0 && p5==1) ap++; int p6 = (pD[j] >0); if(p5==0 && p6==1) ap++; int p7 = (pD[j-1] >0); if(p6==0 && p7==1) ap++; int p8 = (pC[j-1] >0); if(p7==0 && p8==1) ap++; int p9 = (pU[j-1] >0); if(p8==0 && p9==1) ap++; if(p9==0 && p2==1) ap++; if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7){ if(ap==1){ if((p2*p4*p6==0)&&(p4*p6*p8==0)){ dst.ptr<uchar>(i)[j]=0; isFinished =TRUE; } } } } } //掃描過程一 結束 dst.copyTo(tmpImg); //掃描過程二 開始 for(i=1; i<height; i++){ pU = tmpImg.ptr<uchar>(i-1); pC = tmpImg.ptr<uchar>(i); pD = tmpImg.ptr<uchar>(i+1); for(int j=1; j<width; j++){ if(pC[j] > 0){ int ap=0; int p2 = (pU[j] >0); int p3 = (pU[j+1] >0); if (p2==0 && p3==1) ap++; int p4 = (pC[j+1] >0); if(p3==0 && p4==1) ap++; int p5 = (pD[j+1] >0); if(p4==0 && p5==1) ap++; int p6 = (pD[j] >0); if(p5==0 && p6==1) ap++; int p7 = (pD[j-1] >0); if(p6==0 && p7==1) ap++; int p8 = (pC[j-1] >0); if(p7==0 && p8==1) ap++; int p9 = (pU[j-1] >0); if(p8==0 && p9==1) ap++; if(p9==0 && p2==1) ap++; if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7){ if(ap==1){ if((p2*p4*p8==0)&&(p2*p6*p8==0)){ dst.ptr<uchar>(i)[j]=0; isFinished =TRUE; } } } } } } //一次 先行後列掃描完成 //如果在掃描過程中沒有刪除點,則提前退出 if(isFinished ==FALSE) break; } } } #end of thin
//使得rect區域半透明 Mat translucence(Mat src,Rect rect,int idepth){ Mat dst = src.clone(); Mat roi = dst(rect); roi += cv::Scalar(idepth,idepth,idepth); return dst; }
//使得rect區域打上馬賽克 Mat mosaic(Mat src,Rect rect,int W,int H){ Mat dst = src.clone(); Mat roi = dst(rect); for (int i=W; i<roi.cols; i+=W) { for (int j=H; j<roi.rows; j+=H) { uchar s=roi.at<uchar>(j-H/2,(i-W/2)*3); uchar s1=roi.at<uchar>(j-H/2,(i-W/2)*3+1); uchar s2=roi.at<uchar>(j-H/2,(i-W/2)*3+2); for (int ii=i-W; ii<=i; ii++) { for (int jj=j-H; jj<=j; jj++) { roi.at<uchar>(jj,ii*3+0)=s; roi.at<uchar>(jj,ii*3+1)=s1; roi.at<uchar>(jj,ii*3+2)=s2; } } } } return dst; }
//基於顏色直方圖的距離計算 double GetHsVDistance(Mat src_base,Mat src_test1){ Mat hsv_base; Mat hsv_test1; /// Convert to HSV cvtColor( src_base, hsv_base, COLOR_BGR2HSV ); cvtColor( src_test1, hsv_test1, COLOR_BGR2HSV ); /// Using 50 bins for hue and 60 for saturation int h_bins = 50; int s_bins = 60; int histSize[] = { h_bins, s_bins }; // hue varies from 0 to 179, saturation from 0 to 255 float h_ranges[] = { 0, 180 }; float s_ranges[] = { 0, 256 }; const float* ranges[] = { h_ranges, s_ranges }; // Use the o-th and 1-st channels int channels[] = { 0, 1 }; /// Histograms MatND hist_base; MatND hist_test1; /// Calculate the histograms for the HSV images calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false ); normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() ); calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false ); normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() ); /// Apply the histogram comparison methods double base_test1 = compareHist( hist_base, hist_test1, 0 ); return base_test1; }
// Multiply 正片疊底 void Multiply(Mat& src1, Mat& src2, Mat& dst) { for(int index_row=0; index_row<src1.rows; index_row++) { for(int index_col=0; index_col<src1.cols; index_col++) { for(int index_c=0; index_c<3; index_c++) dst.at<Vec3f>(index_row, index_col)[index_c]= src1.at<Vec3f>(index_row, index_col)[index_c]* src2.at<Vec3f>(index_row, index_col)[index_c]; } } }
// Color_Burn 顏色加深 void Color_Burn(Mat& src1, Mat& src2, Mat& dst) { for(int index_row=0; index_row<src1.rows; index_row++) { for(int index_col=0; index_col<src1.cols; index_col++) { for(int index_c=0; index_c<3; index_c++) dst.at<Vec3f>(index_row, index_col)[index_c]=1- (1-src1.at<Vec3f>(index_row, index_col)[index_c])/ src2.at<Vec3f>(index_row, index_col)[index_c]; } } }
// 線性增強 void Linear_Burn(Mat& src1, Mat& src2, Mat& dst) { for(int index_row=0; index_row<src1.rows; index_row++) { for(int index_col=0; index_col<src1.cols; index_col++) { for(int index_c=0; index_c<3; index_c++) dst.at<Vec3f>(index_row, index_col)[index_c]=max( src1.at<Vec3f>(index_row, index_col)[index_c]+ src2.at<Vec3f>(index_row, index_col)[index_c]-1, (float)0.0); } } }
//遞歸讀取目錄下全部文件(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); } } }
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); } }
//創建或續寫目錄下的csv文件,填寫“文件位置-分類”對 int writeCsv(const string& filename,const Vector<pair<string,string>>srcVect,char separator ){ ofstream file(filename.c_str(),ofstream::app); if (!file) return 0; for (int i=0;i<srcVect.size();i++){ file<<srcVect[i].first<<separator<<srcVect[i].second<<endl; } return srcVect.size(); } //讀取目錄下的csv文件,獲得“文件位置-分類”對 vector<pair<string,string>> readCsv(const string& filename, char separator) { pair<string,string> apair; string line, path, classlabel; vector<pair<string,string>> retVect; ifstream file(filename.c_str(), ifstream::in); if (!file) return retVect; while (getline(file, line)) { stringstream liness(line); getline(liness, path, separator); getline(liness, classlabel); if(!path.empty() && !classlabel.empty()) { apair.first = path; apair.second = classlabel; retVect.push_back(apair); } } return retVect; }
//獲得ini文件中的值 CString GetInitString( CString Name1 ,CString Name2){ char c[100] ; memset( c ,0 ,100) ; CString csCfgFilePath; GetModuleFileName(NULL, csCfgFilePath.GetBufferSetLength(MAX_PATH+1), MAX_PATH); csCfgFilePath.ReleaseBuffer(); int nPos = csCfgFilePath.ReverseFind ('\\'); csCfgFilePath = csCfgFilePath.Left (nPos); csCfgFilePath += "\\Config" ; BOOL br = GetPrivateProfileString(Name1,Name2 ,"0",c, 100 , csCfgFilePath) ; CString rstr ; rstr .Format("%s" , c) ; return rstr ; } //寫入ini問價中的值 void WriteInitString( CString Name1 ,CString Name2 ,CString strvalue){ CString csCfgFilePath; GetModuleFileName(NULL, csCfgFilePath.GetBufferSetLength(MAX_PATH+1), MAX_PATH); csCfgFilePath.ReleaseBuffer(); int nPos = csCfgFilePath.ReverseFind ('\\'); csCfgFilePath = csCfgFilePath.Left (nPos); csCfgFilePath += "\\Config" ; BOOL br = WritePrivateProfileString(Name1 ,Name2 ,strvalue ,csCfgFilePath) ; if ( !br) TRACE("savewrong") ; }
//獲得當前目錄路徑 static CString GetLocalPath(){ CString csCfgFilePath; GetModuleFileName(NULL, csCfgFilePath.GetBufferSetLength(MAX_PATH+1), MAX_PATH); csCfgFilePath.ReleaseBuffer(); int nPos = csCfgFilePath.ReverseFind ('\\'); csCfgFilePath = csCfgFilePath.Left (nPos); return csCfgFilePath; } //獲得.exe路徑 static CString GetExePath() { CString strPath; GetModuleFileName(NULL,strPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH); strPath.ReleaseBuffer(); return strPath; }
//開機自動運行 static BOOL SetAutoRun(CString strPath,bool flag) { CString str; HKEY hRegKey; BOOL bResult; str=_T("Software\\Microsoft\\Windows\\CurrentVersion\\Run"); if(RegOpenKey(HKEY_LOCAL_MACHINE, str, &hRegKey) != ERROR_SUCCESS) bResult=FALSE; else { _splitpath(strPath.GetBuffer(0),NULL,NULL,str.GetBufferSetLength(MAX_PATH+1),NULL); strPath.ReleaseBuffer(); str.ReleaseBuffer();//str是鍵的名字 if (flag){ if(::RegSetValueEx( hRegKey,str,0,REG_SZ,(CONST BYTE *)strPath.GetBuffer(0),strPath.GetLength() ) != ERROR_SUCCESS) bResult=FALSE; else bResult=TRUE; }else{ if( ::RegDeleteValue(hRegKey,str) != ERROR_SUCCESS) bResult=FALSE; else bResult=TRUE; } strPath.ReleaseBuffer(); } return bResult; }
//string替換 void string_replace(string & strBig, const string & strsrc, const string &strdst) { string::size_type pos=0; string::size_type srclen=strsrc.size(); string::size_type dstlen=strdst.size(); while( (pos=strBig.find(strsrc, pos)) != string::npos) { strBig.replace(pos, srclen, strdst); pos += dstlen; } }
//C++的spilt函數 void SplitString(const string& s, vector<string>& v, const string& c){ std::string::size_type pos1, pos2; pos2 = s.find(c); pos1 = 0; while(std::string::npos != pos2){ v.push_back(s.substr(pos1, pos2-pos1)); pos1 = pos2 + c.size(); pos2 = s.find(c, pos1); } if(pos1 != s.length()) v.push_back(s.substr(pos1)); }
//! 通過文件夾名稱獲取文件名,不包括後綴 void getFileName(const string& filepath, string& name,string& lastname){ vector<string> spilt_path; SplitString(filepath, spilt_path, "\\"); int spiltsize = spilt_path.size(); string filename = ""; if (spiltsize != 0){ filename = spilt_path[spiltsize-1]; vector<string> spilt_name; SplitString(filename, spilt_name, "."); int name_size = spilt_name.size(); if (name_size != 0) name = spilt_name[0]; lastname = spilt_name[name_size-1]; } }
CString ExportListToExcel(CString sExcelFile,CListCtrl* pList, CString strTitle) { CString warningStr; if (pList->GetItemCount ()>0) { CDatabase database; CString sSql; CString tableName = strTitle; // 檢索是否安裝有Excel驅動 "Microsoft Excel Driver (*.xls)" CString sDriver; sDriver = GetExcelDriver(); if (sDriver.IsEmpty()) { // 沒有發現Excel驅動 AfxMessageBox("沒有安裝Excel!\n請先安裝Excel軟件才能使用導出功能!"); return NULL; } ///默認文件名 /* CString sExcelFile; if (!GetDefaultXlsFileName(sExcelFile)) return NULL;*/ // 創建進行存取的字符串 sSql.Format("DRIVER={%s};DSN='';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s",sDriver, sExcelFile, sExcelFile); // 創建數據庫 (既Excel表格文件) if( database.OpenEx(sSql,CDatabase::noOdbcDialog) ) { // 創建表結構 int i; LVCOLUMN columnData; CString columnName; int columnNum = 0; CString strH; CString strV; sSql = ""; strH = ""; columnData.mask = LVCF_TEXT; columnData.cchTextMax =100; columnData.pszText = columnName.GetBuffer (100); for(i=0;pList->GetColumn(i,&columnData);i++) { if (i!=0) { sSql = sSql + ", " ; strH = strH + ", " ; } sSql = sSql + " " + columnData.pszText +" TEXT"; strH = strH + " " + columnData.pszText +" "; } columnName.ReleaseBuffer (); columnNum = i; sSql = "CREATE TABLE " + tableName + " ( " + sSql + " ) "; database.ExecuteSQL(sSql); // 插入數據項 int nItemIndex; for (nItemIndex=0;nItemIndex<pList->GetItemCount ();nItemIndex++){ strV = ""; for(i=0;i<columnNum;i++) { if (i!=0) { strV = strV + ", " ; } strV = strV + " '" + pList->GetItemText(nItemIndex,i) +"' "; } sSql = "INSERT INTO "+ tableName +" ("+ strH + ")" +" VALUES("+ strV + ")"; database.ExecuteSQL(sSql); } } // 關閉數據庫 database.Close(); return sExcelFile; } }