标签:style http io color ar os 使用 sp for
color space reduction
divide the color space current value with a new input value to end up with fewer colors. For instance every value between zero and nine takes the new value zero, every value between ten and nineteen the value ten and so on.
减少颜色空间数目
Therefore, any fraction will be rounded down. Taking advantage of this fact the upper operation in the uchar domain may be expressed as:
Therefore, for larger images it would be wise to calculate all possible values beforehand and during the assignment just make the assignment, by using a lookup table. Lookup tables are simple arrays (having one or more dimensions) that for a given input value variation holds the final output value.
滤波模板 —— 在需要时分配空间
程序中使用 stringstream 来实现txt到int 的转换
int divideWith = 0; // convert our input string to number - C++ style stringstream s; s << argv[2]; s >> divideWith; if (!s || !divideWith) { cout << "Invalid number entered for dividing. " << endl; return -1; } uchar table[256]; for (int i = 0; i < 256; ++i) table[i] = (uchar)(divideWith * (i/divideWith));
使用 OpenCV 提供的时间计算函数
The first returns the number of ticks of your systems CPU from a certain event (like since you booted your system).
The second returns how many times your CPU emits a tick during a second.
double t = (double)getTickCount(); // do something ... t = ((double)getTickCount() - t)/getTickFrequency(); cout << "Times passed in seconds: " << t << endl;
图像在内存中的存储
注意 RGB图像在内存的存放顺序是BGR
In case of a gray scale image we have something like:
For multichannel images the columns contain as many sub columns as the number of channels. For example in case of an RGB color system:
C语言风格,直接操纵指针是最快的,不解释
We need to look out for color images: we have three channels so we need to pass through three times more items in each row.
Mat& ScanImageAndReduceC(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() != sizeof(uchar)); int channels = I.channels(); int nRows = I.rows; int nCols = I.cols * channels; if (I.isContinuous()) { nCols *= nRows; nRows = 1; } int i,j; uchar* p; for( i = 0; i < nRows; ++i) { p = I.ptr<uchar>(i); for ( j = 0; j < nCols; ++j) { p[j] = table[p[j]]; } } return I; }
C 语言样式的另一种
The data data member of a Mat object returns the pointer to the first row, first column. If this pointer is null you have no valid input in that object. Checking this is the simplest method to check if your image loading was a success. In case the storage is continues we can use this to go through the whole data pointer.
uchar* p = I.data; for( unsigned int i =0; i < ncol*nrows; ++i) *p++ = table[*p];
In case of the efficient way making sure that you pass through the right amount of uchar fields and to skip the gaps that may occur between the rows was your responsibility. 指针方式,安全检查由用户自己完成
The iterator method is considered a safer way as it takes over these tasks from the user. All you need to do is ask the begin and the end of the image matrix and then just increase the begin iterator until you reach the end.
Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() != sizeof(uchar)); const int channels = I.channels(); switch(channels) { case 1: { MatIterator_<uchar> it, end; for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it) *it = table[*it]; break; } case 3: { MatIterator_<Vec3b> it, end; for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it) { (*it)[0] = table[(*it)[0]]; (*it)[1] = table[(*it)[1]]; (*it)[2] = table[(*it)[2]]; } } } return I; }
即时的地址计算,引用返回
It was made to acquire or modify somehow random elements in the image. 这种方法不建议用于遍历图像,而是随机访问图像中某个像素
Its basic usage is to specify the row and column number of the item you want to access.
If you need to multiple lookups using this method for an image it may be troublesome and time consuming to enter the type and the at keyword for each of the accesses.
Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() != sizeof(uchar)); const int channels = I.channels(); switch(channels) { case 1: { for( int i = 0; i < I.rows; ++i) for( int j = 0; j < I.cols; ++j ) I.at<uchar>(i,j) = table[I.at<uchar>(i,j)]; break; } case 3: { Mat_<Vec3b> _I = I; for( int i = 0; i < I.rows; ++i) for( int j = 0; j < I.cols; ++j ) { _I(i,j)[0] = table[_I(i,j)[0]]; _I(i,j)[1] = table[_I(i,j)[1]]; _I(i,j)[2] = table[_I(i,j)[2]]; } I = _I; break; } } return I; }
全部程序如下:
// testOpencv1.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> #include <sstream> using namespace std; using namespace cv; static void help() { cout << "\n--------------------------------------------------------------------------" << endl << "This program shows how to scan image objects in OpenCV (cv::Mat). As use case" << " we take an input image and divide the native color palette (255) with the " << endl << "input. Shows C operator[] method, iterators and at function for on-the-fly item address calculation."<< endl << "Usage:" << endl << "./howToScanImages imageNameToUse divideWith [G]" << endl << "if you add a G parameter the image is processed in gray scale" << endl << "--------------------------------------------------------------------------" << endl << endl; } Mat& ScanImageAndReduceC(Mat& I, const uchar* table); Mat& ScanImageAndReduceIterator(Mat& I, const uchar* table); Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar * table); int main( int argc, char* argv[]) { help(); if (argc < 3) { cout << "Not enough parameters" << endl; return -1; } Mat I, J; if( argc == 4 && !strcmp(argv[3],"G") ) I = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); else I = imread(argv[1], CV_LOAD_IMAGE_COLOR); if (!I.data) { cout << "The image" << argv[1] << " could not be loaded." << endl; return -1; } int divideWith = 0; // convert our input string to number - C++ style stringstream s; s << argv[2]; s >> divideWith; if (!s || !divideWith) { cout << "Invalid number entered for dividing. " << endl; return -1; } uchar table[256]; for (int i = 0; i < 256; ++i) table[i] = (uchar)(divideWith * (i/divideWith)); const int times = 100; double t; t = (double)getTickCount(); for (int i = 0; i < times; ++i) { cv::Mat clone_i = I.clone(); J = ScanImageAndReduceC(clone_i, table); } t = 1000*((double)getTickCount() - t)/getTickFrequency(); t /= times; cout << "Time of reducing with the C operator [] (averaged for " << times << " runs): " << t << " milliseconds."<< endl; t = (double)getTickCount(); for (int i = 0; i < times; ++i) { cv::Mat clone_i = I.clone(); J = ScanImageAndReduceIterator(clone_i, table); } t = 1000*((double)getTickCount() - t)/getTickFrequency(); t /= times; cout << "Time of reducing with the iterator (averaged for " << times << " runs): " << t << " milliseconds."<< endl; t = (double)getTickCount(); for (int i = 0; i < times; ++i) { cv::Mat clone_i = I.clone(); ScanImageAndReduceRandomAccess(clone_i, table); } t = 1000*((double)getTickCount() - t)/getTickFrequency(); t /= times; cout << "Time of reducing with the on-the-fly address generation - at function (averaged for " << times << " runs): " << t << " milliseconds."<< endl; Mat lookUpTable(1, 256, CV_8U); uchar* p = lookUpTable.data; for( int i = 0; i < 256; ++i) p[i] = table[i]; t = (double)getTickCount(); for (int i = 0; i < times; ++i) LUT(I, lookUpTable, J); t = 1000*((double)getTickCount() - t)/getTickFrequency(); t /= times; cout << "Time of reducing with the LUT function (averaged for " << times << " runs): " << t << " milliseconds."<< endl; return 0; } Mat& ScanImageAndReduceC(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() != sizeof(uchar)); int channels = I.channels(); int nRows = I.rows; int nCols = I.cols * channels; if (I.isContinuous()) // 矩阵数据是否连续排列 { nCols *= nRows; nRows = 1; } int i,j; uchar* p; for( i = 0; i < nRows; ++i) // 从头到尾 { p = I.ptr<uchar>(i); for ( j = 0; j < nCols; ++j) { p[j] = table[p[j]]; // 将每个像素的映射值重新填回 } } return I; } Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() != sizeof(uchar)); // 错误检测 ~~ const int channels = I.channels(); switch(channels) { case 1: { MatIterator_<uchar> it, end; for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it) *it = table[*it]; break; } case 3: { MatIterator_<Vec3b> it, end; for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it) { (*it)[0] = table[(*it)[0]]; (*it)[1] = table[(*it)[1]]; (*it)[2] = table[(*it)[2]]; } } } return I; } Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() != sizeof(uchar)); const int channels = I.channels(); switch(channels) { case 1: { for( int i = 0; i < I.rows; ++i) for( int j = 0; j < I.cols; ++j ) I.at<uchar>(i,j) = table[I.at<uchar>(i,j)]; break; } case 3: { Mat_<Vec3b> _I = I; for( int i = 0; i < I.rows; ++i) for( int j = 0; j < I.cols; ++j ) { _I(i,j)[0] = table[_I(i,j)[0]]; _I(i,j)[1] = table[_I(i,j)[1]]; _I(i,j)[2] = table[_I(i,j)[2]]; } I = _I; break; } } return I; }
OpenCV Tutorials —— Scan images
标签:style http io color ar os 使用 sp for
原文地址:http://www.cnblogs.com/sprint1989/p/4101502.html