OpenCV:遍历图像

事例

对图像每一个像素使用变换公式 I n e w = I o l d d i v i d e W i t h ∗ d i v i d e W i t h I_{new} = \frac{I_{old}}{divideWith} * divideWith Inew=divideWithIolddivideWith I o l d 和 d i v i d e W i t h I_{old}和divideWith IolddivideWith为命令行输入

#include <iostream>
#include <opencv2/opencv.hpp>

cv::Mat &ScanImageAndReduceC(cv::Mat &I, const uchar *const table);
cv::Mat &ScanImageAndReduceIterator(cv::Mat &I, const uchar *const table);
cv::Mat &ScanImageAndReduceRandomAccess(cv::Mat &I, const uchar *const table);

int main(int argc, char **argv) {
  cv::String imageName = argv[1]; // 获取图像地址
  cv::Mat img = cv::imread(imageName, cv::IMREAD_UNCHANGED); // 读取图像
  // 判断是否成功读取
  if (argc != 3 || !img.data) {
    std::cout << "Can't open file: " << imageName << std::endl;
    return -1;
  }

  int divideWith = 0; // convert our input string to number - c++ style
  std::stringstream s;
  s << argv[2];
  s >> divideWith;
  if (!s || !divideWith) {
    std::cout << "Invalid number entered for dividing" << std::endl;
    return -1;
  }

  // Lookup Table
  uchar table[256];
  for (int i = 0; i < 256; ++i)
    table[i] = (uchar)(divideWith * (i / divideWith));

  /*
    double t = (double)cv::getTickCount();
    // do something...
    t = ((double)cv::getTickCount() - t) / cv::getTickFrequency();
  */

  double t;
  // The efficient way
  t = (double)cv::getTickCount();
  ScanImageAndReduceC(img, table);
  t = ((double)cv::getTickCount() - t) / cv::getTickFrequency();
  std::cout << "Times passed in seconds (Efficient): " << t * 1000 << " ms" << std::endl;

  // The iterator(safe) method
  img = cv::imread(imageName, cv::IMREAD_UNCHANGED);
  t = (double)cv::getTickCount();
  ScanImageAndReduceIterator(img, table);
  t = ((double)cv::getTickCount() - t) / cv::getTickFrequency();
  std::cout << "Times passed in seconds (Iterator): " << t * 1000 << " ms" << std::endl;

  // On-the-fly address calculation with reference returing
  img = cv::imread(imageName, cv::IMREAD_UNCHANGED);
  t = (double)cv::getTickCount();
  ScanImageAndReduceRandomAccess(img, table);
  t = ((double)cv::getTickCount() - t) / cv::getTickFrequency();
  std::cout << "Times passed in seconds (On-The-Fly RA): " << t * 1000 << " ms" << std::endl;

  // LUT function
  img = cv::imread(imageName, cv::IMREAD_UNCHANGED);
  cv::Mat J;			// J is the output image.
  cv::Mat LookUpTable(1, 256, CV_8U);
  uchar *p = LookUpTable.ptr();
  for(int i = 0; i < 256; ++i)
    p[i] = table[i];
  t = (double)cv::getTickCount();
  cv::LUT(img, LookUpTable, J);
  t = ((double)cv::getTickCount() - t) / cv::getTickFrequency();
  std::cout << "Times passed in seconds (LUT function): " << t * 1000 << "ms" << std::endl;
  
  return 0;
}

cv::Mat &ScanImageAndReduceC(cv::Mat &I, const uchar *const table) {
  // accept only char type matrices.
  CV_Assert(I.depth() == CV_8U);

  int nRows = I.rows;
  int nCols = I.cols * I.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;
}

cv::Mat &ScanImageAndReduceIterator(cv::Mat &I, const uchar *const table) {
  // accept onlt char type matricex
  CV_Assert(I.depth() == CV_8U);

  const int channels = I.channels();
  switch (channels) {
  case 1: {
    cv::MatIterator_<uchar> it, end;
    for (it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
      *it = table[*it];
    break;
  }
  case 3: {
    cv::MatIterator_<cv::Vec3b> it, end;
    for (it = I.begin<cv::Vec3b>(), end = I.end<cv::Vec3b>(); it != end; ++it) {
      (*it)[0] = table[(*it)[0]];
      (*it)[1] = table[(*it)[1]];
      (*it)[2] = table[(*it)[2]];
    }
  }
  }

  return I;
}

cv::Mat &ScanImageAndReduceRandomAccess(cv::Mat &I, const uchar *const table) {
  // accept only char type matrices
  CV_Assert(I.depth() == CV_8U);

  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: {
    cv::Mat_<cv::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;
}

cv::LUT( )速度最快

Times passed in seconds (Efficient): 25.7123 ms
Times passed in seconds (Iterator): 60.7759 ms
Times passed in seconds (On-The-Fly RA): 67.339 ms
Times passed in seconds (LUT function): 19.2237ms
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值