opencv版本号: opencv3.4.1
目录
图像处理中需要对图像的像素点进行遍历,遍历图像像素的算法影响运行速度;以图像反色为例,有以下几种算法;
- cv::Mat inverseColor1(cv::Mat srcImage)
- {
- cv::Mat tempImage = srcImage.clone();
- int row = tempImage.rows;
- int col = tempImage.cols;
-
- for(int i = 0; i < row; i++){
- for(int j = 0; j < col; j++){
- //对各个通道进行反色处理
- tempImage.at
(i,j)[0] = 255 - srcImage.at(i,j)[0]; - tempImage.at
(i,j)[1] = 255 - srcImage.at(i,j)[1]; - tempImage.at
(i,j)[2] = 255 - srcImage.at(i,j)[2]; - }
- }
-
- return tempImage;
- }
- cv::Mat inverseColor2(cv::Mat srcImage)
- {
- cv::Mat tempImage = srcImage.clone();
- int row = tempImage.rows;
-
- //将3通道转换为单通道
- //std::cout << " row=" << row << " cols=" << tempImage.cols << " channels=" << tempImage.channels() << endl;
- int nStep = tempImage.cols * tempImage.channels();
-
- for(int i = 0; i < row; i++){
- //取源图像指针
- const uchar *pSrcData = srcImage.ptr
(i); -
- uchar *pResultData = tempImage.ptr
(i); - for(int j = 0; j < nStep; j++){
- pResultData[j] = cv::saturate_cast
(255-pSrcData[j]); - }
- }
-
- return tempImage;
- }
- cv::Mat inverseColor3(cv :: Mat srcImage)
- {
- cv::Mat tempImage = srcImage.clone();
-
- //初始化源图像迭代器
- cv::MatConstIterator_
srcIterStart = srcImage.begin(); - cv::MatConstIterator_
srcIterEnd = srcImage.end(); -
- //初始化输出图像迭代器
- cv::MatIterator_
resIterStart = tempImage.begin(); - cv::MatIterator_
resIterEnd = tempImage.end(); -
- while(srcIterStart != srcIterEnd)
-
- {
- (*resIterStart)[0] = 255 - (*srcIterStart)[0];
- (*resIterStart)[1] = 255 - (*srcIterStart)[1];
- (*resIterStart)[2] = 255 - (*srcIterStart)[2];
-
- srcIterStart++;
- resIterStart++;
- }
-
- return tempImage;
- }
图像数据的存储行与行间可能是空白单元,即图像行与行间的存储可能是不连续的,所以在使用上述方法进行图像的遍历时,很大程度上会造成指针的移动浪费;所以用isContunuout函数判断图像元素存储是连续的;
- cv::Mat inverseColor4(cv :: Mat srcImage)
- {
- int row = srcImage.rows;
- int col = srcImage.cols;
- cv::Mat tempImage = srcImage.clone();
-
- //判断是否有连续图像,即是否有像素填充
- if(srcImage.isContinuous() && tempImage.isContinuous()){
- row = 1;
- col = col * srcImage.rows * srcImage.channels();
- }
-
- for(int i = 0 ;i < row; i++){
- const uchar *pSrcData = srcImage.ptr
(i); - uchar *pResultData = tempImage.ptr
(i); - for(int j =0 ; j < col; j++){
- *pResultData = 255 - *pSrcData;
-
- pResultData++;
- pSrcData++;
- }
- }
-
- return tempImage;
- }
为了减少图像映射的时间复杂度,提供了查找表LUT;
- cv::Mat inverseColor5(cv :: Mat srcImage)
- {
- int row = srcImage.rows;
- int col = srcImage.cols;
- cv::Mat tempImage = srcImage.clone();
-
- //建立LUT反色table
- uchar LutTab[256];
- for(int i =0 ; i < 256; i++){
- LutTab[i] = 255 - i;
- }
-
- cv::Mat lookUpTable(1, 256, CV_8U);
- uchar *pData = lookUpTable.data;
-
- //建立映射表
- for(int i = 0; i < 256; i++){
- pData[i] = LutTab[i];
- }
-
- //利用索引查找
- cv::LUT(srcImage, lookUpTable, tempImage);
-
- return tempImage;
- }
测试代码:
- int main()
- {
- cv::Mat srcImage = cv::imread("./lena.jpg");
- if(srcImage.empty()){
- std::cout << "imread failed" << endl;
- return -1;
- }
-
- double tTime;
- tTime = (double)getTickCount();
-
- //cv::Mat dstImage = inverseColor1(srcImage); //运行时间Max 7.30422
- //cv::Mat dstImage = inverseColor2(srcImage); //运行时间Max 1.88004
- //cv::Mat dstImage = inverseColor3(srcImage); //运行时间Max 8.38001
- //cv::Mat dstImage = inverseColor4(srcImage); //运行时间Max 1.66753
- cv::Mat dstImage = inverseColor5(srcImage); //运行时间Max 1.26254
-
- tTime = 1000 * ((double)getTickCount() - tTime) / getTickFrequency();
- std::cout << tTime << std::endl;
-
- cv::imwrite("./lena_inverse5.jpg", dstImage);
-
- return 0;
- }
getTickCount()和getTickFrequency()函数用来计时测试代码的运行时间;