1、 图像的遍历
OpenCV图像遍历最高效的方法是指针遍历方法。因为图像在OpenCV里的存储机制问题,行与行之间可能有空白单元(一般是补够4的倍数或8的倍数,有些地方也称作“位对齐”)。这些空白单元对图像来说是没有意思的,只是为了在某些架构上能够更有效率,比如intel MMX可以更有效的处理那种个数是4或8倍数的行。Mat提供了一个检测图像是否连续的函数isContinuous()。当图像连通时,我们就可以把图像完全展开,看成是一行。因此最高效的遍历方法如下:
void imageCopy(const Mat& image,Mat& outImage) { int nr=image.rows; int nc=image.cols; outImage.create(image.size(),image.type()); if(image.isContinuous()&&outImage.isContinuous()) {nr=1;nc=nc*image.rows*image.channels();} for(int i=0;i<nr;i++) { const uchar* inData=image.ptr<uchar>(i); uchar* outData=outImage.ptr<uchar>(i); for(int j=0;j<nc;j++) {*outData++=*inData++;}}
}
// create the accumulation histograms, img is a binary image, t is 水平或垂直Mat CalcHistogram(Mat img, int t) {int sz = (t) ? img.rows : img.cols;Mat mhist = Mat::zeros(1, sz, CV_32F);for(int j = 0; j < sz; j++){Mat data = (t) ? img.row(j) : img.col(j);// 统计这一行或一列中,非零元素的个数,并保存到mhist中mhist.at<float>(j) = countNonZero(data);}double min, max;// Normalize histogramminMaxLoc(mhist, &min, &max);if (max > 0){// 用mhist直方图中的最大值,归一化直方图mhist.convertTo(mhist, -1, 1.0f/max, 0);}return mhist;}
//! 获得字符的特征图Mat features(Mat in, int sizeData) {//Histogram featuresMat vhist = ProjectedHistogram(in, VERTICAL);Mat hhist = ProjectedHistogram(in, HORIZONTAL);//Low data featureMat lowData;resize(in, lowData, Size(sizeData, sizeData));//Last 10 is the number of moments componentsint numCols = vhist.cols + hhist.cols + lowData.cols * lowData.cols;Mat out = Mat::zeros(1, numCols, CV_32F);//Asign values to feature, ANN的样本特征为水平、垂直直方图和低分辨率图像所组成的矢量int j = 0;for(int i = 0; i < vhist.cols; i++){out.at<float>(j) = vhist.at<float>(i);j++;}for(int i = 0; i < hhist.cols; i++){out.at<float>(j) = hhist.at<float>(i);j++;}for(int x=0; x<lowData.cols; x++){for(int y=0; y<lowData.rows; y++){out.at<float>(j)=(float)lowData.at<unsigned char>(x,y);j++;}}return out;}