[关闭]
@FE40536 2019-07-21T21:27:53.000000Z 字数 30518 阅读 906

opencv学习笔记

列表项


C++ opencv


  1. 解释框
  2. //###########################explanation##########################
  3. //################################################################

My Clion project structure(Just for reference, adjust the structure as you need)

project //工程名

bin //可执行文件

cmake-build-debug //调试

img //存放图片

include //头文件

src //.c,.cpp文件

CMakeLists.txt //src中的CMakeLists文件

CMakeLists.txt //project中的CMakeLists文件



  1. #src中的CMakeLists.txt
  2. aux_source_directory (. SRC_LIST)
  3. add_definitions (-DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_THREAD_USE_LIB)
  4. find_package (OpenCV REQUIRED)
  5. find_package (Threads REQUIRED)
  6. find_package (Boost REQUIRED)
  7. include_directories (../include ${OpenCV_INCLUDE_DIRS})
  8. link_directories (/usr/local/lib)
  9. set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
  10. set (OpenCV_DIR /usr/local/share/OpenCV)
  11. set (CMAKE_CXX_STANDARD 11)
  12. set (BOOST_ROOT /usr/local/inlcude/boost)
  13. add_executable (main ${SRC_LIST})
  14. target_link_libraries (main ${OpenCV_LIBS} ${BOOST_LIBRARYDIR} boost_thread boost_system Threads::Threads)



  1. #project中的CMakeLists.txt文件
  2. cmake_minimum_required(VERSION 2.8)
  3. project(untitled)
  4. add_subdirectory(src)

Load and Display an Image

Source Code & Analyzing

Mat

imread

namedWindow

imshow

waitKey

  1. #include <opencv2/core.hpp>
  2. #include <opencv2/imgcodecs.hpp>
  3. #include <opencv2/highgui.hpp>
  4. #include <iostream>
  5. #include <string>
  6. using namespace cv;
  7. using namespace std;
  8. int main( int argc, char** argv )
  9. {
  10. //###########################explanation##########################
  11. //设置默认文件名,若含有参数图片则用参数图片,无则用默认的
  12. //################################################################
  13. String imageName( "./fall.jpg" ); // by default
  14. if( argc > 1)
  15. {
  16. imageName = argv[1];
  17. }
  18. //###########################explanation##########################
  19. //Mat类用于存放图片,再用imread来读取图片,imread有三种形式
  20. //IMREAD_UNCHANGED (<0) 不做变化的载入图片
  21. //IMREAD_GRAYSCALE (=0) 以纯灰度的格式载入图片
  22. //IMREAD_COLOR () 以RGB格式载入图片
  23. //################################################################
  24. Mat image;
  25. image = imread( imageName, IMREAD_COLOR ); // Read the file
  26. //###########################explanation##########################
  27. //判断是否有图像文件
  28. //################################################################
  29. if( image.empty() ) // Check for invalid input
  30. {
  31. cout << "Could not open or find the image" << std::endl ;
  32. return -1;
  33. }
  34. //###########################explanation##########################
  35. //namedWindow("Display window",WINDOW_AUTOSIZE);
  36. //第二个参数WINDOW_AUTOSIZE表示按图像原大小展示,且窗口不能缩放
  37. //WINDOW_NORMAL 窗口可以缩放
  38. //WINDOW_KEEPRATIO 保持比例缩放
  39. //WINDOW_FREERATIO 允许不按比例缩放
  40. //################################################################
  41. namedWindow( "Display window", WINDOW_AUTOSIZE ); // Create a window for display.
  42. //###########################explanation##########################
  43. //imshow("窗口名称",存储图像的容器);
  44. //该函数用于在用namedWindow命名好的窗口展示Mat类image对象存储的图片,窗口名称以imshow里的名称为主
  45. //当namedWindow里的窗口名字和imshow的窗口名字不一样时会有两个窗口出现,最好让名字保持一致,可以用一个变量来统一一下
  46. //################################################################
  47. imshow( "Display window", image ); // Show our image inside it.
  48. //###########################explanation##########################
  49. //waitKey(0); 用来防止窗口关闭,括号内参数按毫秒来计算,0代表一直开启知道按下任意键
  50. //################################################################
  51. waitKey(0); // Wait for a keystroke in the window
  52. return 0;
  53. }




Load, Modify, and Save an Image

code

cvtColor

imwrite

这段代码运行的时候用控制台运行并加上图片文件才会有效果

  1. #include <opencv2/opencv.hpp>
  2. using namespace cv;
  3. int main(int argc, char **argv) {
  4. //###########################explanation##########################
  5. //得到图片参数的名字
  6. //################################################################
  7. char *imageName = argv[1];
  8. //###########################explanation##########################
  9. //用Mat容器存储imread得到的图片
  10. //################################################################
  11. Mat image;
  12. image = imread(imageName, IMREAD_COLOR);
  13. //###########################explanation##########################
  14. //判断是否得到图片
  15. //################################################################
  16. if (argc != 2 || !image.data) {
  17. printf(" No image data \n ");
  18. return -1;
  19. }
  20. //###########################explanation##########################
  21. //用Mat类创建一个新的灰度图对象gray_image
  22. //################################################################
  23. Mat gray_image;
  24. //###########################explanation##########################
  25. //ctvColor函数需要三个参数(源图像,目标图像,转换方式)
  26. //COLOR_BGR2GRAY 是BGR图像转化为灰度图
  27. //################################################################
  28. cvtColor(image, gray_image, COLOR_BGR2GRAY);
  29. //###########################explanation##########################
  30. //得到了灰度图后用imwrite函数进行保存
  31. //参数为(保存路径,图像对象)
  32. //################################################################
  33. imwrite("../../images/Gray_Image.jpg", gray_image);
  34. namedWindow(imageName, WINDOW_AUTOSIZE);
  35. namedWindow("Gray image", WINDOW_AUTOSIZE);
  36. imshow(imageName, image);
  37. imshow("Gray image", gray_image);
  38. waitKey(0);
  39. return 0;
  40. }

Mat - The Basic Image Container

definition

  1. Mat A, C; // creates just the header parts
  2. A = imread(argv[1], IMREAD_COLOR); // here we'll know the method used (allocate matrix)
  3. Mat B(A); // Use the copy constructor
  4. C = A; // Assignment operator

ABC全部指向同一个矩阵,但是头部却不一样



devide Mat

  1. Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
  2. Mat E = A(Range::all(), Range(1,3)); // using row and column boundaries

可以用Mat存储原图像的一小部分,用长方形或行列来确定边界



copy Mat

  1. Mat F = A.clone();
  2. Mat G;
  3. A.copyTo(G);




Creating a Mat object explicitly

cv::Mat::Mat Constructor

  1. //###########################explanation##########################
  2. //2,2表示2*2矩阵,CV_8UC3表示用3个数来表示矩阵的一个位置,同理CV_8UC4用4个数表示矩阵的一个位置
  3. //CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]
  4. //################################################################
  5. Mat M(2,2, CV_8UC3, Scalar(0,0,255));
  6. cout << "M = " << endl << " " << M << endl << endl;


Use C/C++ arrays and initialize via constructor

  1. int sz[3] = {2,2,2};
  2. Mat L(3,sz, CV_8UC(1), Scalar::all(0));


cv::Mat::create function

不能初始化矩阵,只能重新分配矩阵大小

  1. M.create(4,4, CV_8UC(2));
  2. cout << "M = "<< endl << " " << M << endl << endl;


MATLAB style initializer: cv::Mat::zeros , cv::Mat::ones , cv::Mat::eye

  1. Mat E = Mat::eye(4, 4, CV_64F);
  2. cout << "E = " << endl << " " << E << endl << endl;
  3. Mat O = Mat::ones(2, 2, CV_32F);
  4. cout << "O = " << endl << " " << O << endl << endl;
  5. Mat Z = Mat::zeros(3,3, CV_8UC1);
  6. cout << "Z = " << endl << " " << Z << endl << endl;


For small matrices you may use comma separated initializers or initializer lists

  1. Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
  2. cout << "C = " << endl << " " << C << endl << endl;
  3. C = (Mat_<double>({0, 1, -1, 0, -1, 2, 5, -1, 0, 5, -1, 0, 1, 0, -1, 0})).reshape(4);
  4. cout << "C = " << endl << " " << C << endl << endl;


Create a new header for an existing Mat object and cv::Mat::clone or cv::Mat::copyTo it

  1. Mat RowClone = C.row(1).clone();
  2. cout << "RowClone = " << endl << " " << RowClone << endl << endl;


random fill

  1. Mat R = Mat(3, 2, CV_8UC3);
  2. randu(R, Scalar::all(0), Scalar::all(255));
  3. cout << "R (default) = " << endl << R << endl << endl;


Output formatting

Default

  1. cout << "R (default) = " << endl << R << endl << endl;


Python

  1. cout << "R (python) = " << endl << format(R, Formatter::FMT_PYTHON) << endl << endl;


Comma separated values (CSV)

  1. cout << "R (csv) = " << endl << format(R, Formatter::FMT_CSV ) << endl << endl;


Numpy

  1. cout << "R (numpy) = " << endl << format(R, Formatter::FMT_NUMPY ) << endl << endl;


C

  1. cout << "R (c) = " << endl << format(R, Formatter::FMT_C ) << endl << endl;


Output of other commom items

2D Point

  1. Point2f P(5, 1);
  2. cout << "Point (2D) = " << P << endl << endl;


3D Point

  1. Point3f P3f(2, 6, 7);
  2. cout << "Point (3D) = " << P3f << endl << endl;


std::vector voa cv::Mat

  1. vector<float> v;
  2. v.push_back( (float)CV_PI);
  3. v.push_back(2);
  4. v.push_back(3.01f);
  5. cout << "Vector of floats via Mat = " << Mat(v) << endl << endl;


std::vector of points

  1. vector<Point2f> vPoints(20);
  2. for (size_t i = 0; i < vPoints.size(); ++i)
  3. vPoints[i] = Point2f((float)(i * 5), (float)(i % 7));
  4. cout << "A vector of 2D Points = " << vPoints << endl << endl;

How to scan images, lookup tables and time measurement with OpenCV


source code

  1. #include <opencv2/core.hpp>
  2. #include <opencv2/core/utility.hpp>
  3. #include "opencv2/imgcodecs.hpp"
  4. #include <opencv2/highgui.hpp>
  5. #include <iostream>
  6. #include <sstream>
  7. using namespace std;
  8. using namespace cv;
  9. static void help()
  10. {
  11. cout
  12. << "\n--------------------------------------------------------------------------" << endl
  13. << "This program shows how to scan image objects in OpenCV (cv::Mat). As use case"
  14. << " we take an input image and divide the native color palette (255) with the " << endl
  15. << "input. Shows C operator[] method, iterators and at function for on-the-fly item address calculation."<< endl
  16. << "Usage:" << endl
  17. << "./how_to_scan_images <imageNameToUse> <divideWith> [G]" << endl
  18. << "if you add a G parameter the image is processed in gray scale" << endl
  19. << "--------------------------------------------------------------------------" << endl
  20. << endl;
  21. }
  22. Mat& ScanImageAndReduceC(Mat& I, const uchar* table);
  23. Mat& ScanImageAndReduceIterator(Mat& I, const uchar* table);
  24. Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar * table);
  25. int main( int argc, char* argv[])
  26. {
  27. help();
  28. if (argc < 3)
  29. {
  30. cout << "Not enough parameters" << endl;
  31. return -1;
  32. }
  33. //###########################explanation##########################
  34. //读取图像
  35. //################################################################
  36. Mat I, J;
  37. if( argc == 4 && !strcmp(argv[3],"G") )
  38. I = imread(argv[1], IMREAD_GRAYSCALE);
  39. else
  40. I = imread(argv[1], IMREAD_COLOR);
  41. if (I.empty())
  42. {
  43. cout << "The image" << argv[1] << " could not be loaded." << endl;
  44. return -1;
  45. }
  46. //###########################explanation##########################
  47. //用stringstream来得到int型的dividewidth
  48. //################################################################
  49. //! [dividewith]
  50. int divideWith = 0; // convert our input string to number - C++ style
  51. stringstream s;
  52. s << argv[2];
  53. s >> divideWith;
  54. if (!s || !divideWith)
  55. {
  56. cout << "Invalid number entered for dividing. " << endl;
  57. return -1;
  58. }
  59. //###########################explanation##########################
  60. //lookup table
  61. //################################################################
  62. uchar table[256];
  63. for (int i = 0; i < 256; ++i)
  64. table[i] = (uchar)(divideWith * (i/divideWith));
  65. //! [dividewith]
  66. const int times = 100;
  67. double t;
  68. //###########################explanation##########################
  69. //检测时间
  70. //################################################################
  71. t = (double)getTickCount();
  72. for (int i = 0; i < times; ++i)
  73. {
  74. cv::Mat clone_i = I.clone();
  75. J = ScanImageAndReduceC(clone_i, table);
  76. }
  77. t = 1000*((double)getTickCount() - t)/getTickFrequency();
  78. t /= times;
  79. cout << "Time of reducing with the C operator [] (averaged for "
  80. << times << " runs): " << t << " milliseconds."<< endl;
  81. t = (double)getTickCount();
  82. for (int i = 0; i < times; ++i)
  83. {
  84. cv::Mat clone_i = I.clone();
  85. J = ScanImageAndReduceIterator(clone_i, table);
  86. }
  87. t = 1000*((double)getTickCount() - t)/getTickFrequency();
  88. t /= times;
  89. cout << "Time of reducing with the iterator (averaged for "
  90. << times << " runs): " << t << " milliseconds."<< endl;
  91. t = (double)getTickCount();
  92. for (int i = 0; i < times; ++i)
  93. {
  94. cv::Mat clone_i = I.clone();
  95. ScanImageAndReduceRandomAccess(clone_i, table);
  96. }
  97. t = 1000*((double)getTickCount() - t)/getTickFrequency();
  98. t /= times;
  99. cout << "Time of reducing with the on-the-fly address generation - at function (averaged for "
  100. << times << " runs): " << t << " milliseconds."<< endl;
  101. //! [table-init]
  102. Mat lookUpTable(1, 256, CV_8U);
  103. uchar* p = lookUpTable.ptr();
  104. for( int i = 0; i < 256; ++i)
  105. p[i] = table[i];
  106. //! [table-init]
  107. t = (double)getTickCount();
  108. for (int i = 0; i < times; ++i)
  109. //! [table-use]
  110. LUT(I, lookUpTable, J);
  111. //! [table-use]
  112. t = 1000*((double)getTickCount() - t)/getTickFrequency();
  113. t /= times;
  114. cout << "Time of reducing with the LUT function (averaged for "
  115. << times << " runs): " << t << " milliseconds."<< endl;
  116. return 0;
  117. }
  118. //! [scan-c]
  119. Mat& ScanImageAndReduceC(Mat& I, const uchar* const table)
  120. {
  121. // accept only char type matrices
  122. CV_Assert(I.depth() == CV_8U);
  123. int channels = I.channels();
  124. int nRows = I.rows;
  125. int nCols = I.cols * channels;
  126. if (I.isContinuous())
  127. {
  128. nCols *= nRows;
  129. nRows = 1;
  130. }
  131. int i,j;
  132. uchar* p;
  133. for( i = 0; i < nRows; ++i)
  134. {
  135. p = I.ptr<uchar>(i);
  136. for ( j = 0; j < nCols; ++j)
  137. {
  138. p[j] = table[p[j]];
  139. }
  140. }
  141. return I;
  142. }
  143. //! [scan-c]
  144. //! [scan-iterator]
  145. Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
  146. {
  147. // accept only char type matrices
  148. CV_Assert(I.depth() == CV_8U);
  149. const int channels = I.channels();
  150. switch(channels)
  151. {
  152. case 1:
  153. {
  154. MatIterator_<uchar> it, end;
  155. for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
  156. *it = table[*it];
  157. break;
  158. }
  159. case 3:
  160. {
  161. MatIterator_<Vec3b> it, end;
  162. for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
  163. {
  164. (*it)[0] = table[(*it)[0]];
  165. (*it)[1] = table[(*it)[1]];
  166. (*it)[2] = table[(*it)[2]];
  167. }
  168. }
  169. }
  170. return I;
  171. }
  172. //! [scan-iterator]
  173. //! [scan-random]
  174. Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table)
  175. {
  176. // accept only char type matrices
  177. CV_Assert(I.depth() == CV_8U);
  178. const int channels = I.channels();
  179. switch(channels)
  180. {
  181. case 1:
  182. {
  183. for( int i = 0; i < I.rows; ++i)
  184. for( int j = 0; j < I.cols; ++j )
  185. I.at<uchar>(i,j) = table[I.at<uchar>(i,j)];
  186. break;
  187. }
  188. case 3:
  189. {
  190. Mat_<Vec3b> _I = I;
  191. for( int i = 0; i < I.rows; ++i)
  192. for( int j = 0; j < I.cols; ++j )
  193. {
  194. _I(i,j)[0] = table[_I(i,j)[0]];
  195. _I(i,j)[1] = table[_I(i,j)[1]];
  196. _I(i,j)[2] = table[_I(i,j)[2]];
  197. }
  198. I = _I;
  199. break;
  200. }
  201. }
  202. return I;
  203. }
  204. //! [scan-random]



Mask operations on matrices


code

  1. #include <opencv2/imgcodecs.hpp>
  2. #include <opencv2/highgui.hpp>
  3. #include <opencv2/imgproc.hpp>
  4. #include <iostream>
  5. using namespace std;
  6. using namespace cv;
  7. static void help(char* progName)
  8. {
  9. cout << endl
  10. << "This program shows how to filter images with mask: the write it yourself and the"
  11. << "filter2d way. " << endl
  12. << "Usage:" << endl
  13. << progName << " [image_path -- default ../data/lena.jpg] [G -- grayscale] " << endl << endl;
  14. }
  15. void Sharpen(const Mat& myImage,Mat& Result);
  16. int main( int argc, char* argv[])
  17. {
  18. help(argv[0]);
  19. const char* filename = argc >=2 ? argv[1] : "../data/lena.jpg";
  20. Mat src, dst0, dst1;
  21. if (argc >= 3 && !strcmp("G", argv[2]))
  22. src = imread( filename, IMREAD_GRAYSCALE);
  23. else
  24. src = imread( filename, IMREAD_COLOR);
  25. if (src.empty())
  26. {
  27. cerr << "Can't open image [" << filename << "]" << endl;
  28. return -1;
  29. }
  30. namedWindow("Input", WINDOW_AUTOSIZE);
  31. namedWindow("Output", WINDOW_AUTOSIZE);
  32. imshow( "Input", src );
  33. double t = (double)getTickCount();
  34. Sharpen( src, dst0 );
  35. t = ((double)getTickCount() - t)/getTickFrequency();
  36. cout << "Hand written function time passed in seconds: " << t << endl;
  37. imshow( "Output", dst0 );
  38. waitKey();
  39. Mat kernel = (Mat_<char>(3,3) << 0, -1, 0,
  40. -1, 5, -1,
  41. 0, -1, 0);
  42. t = (double)getTickCount();
  43. //###########################explanation##########################
  44. //filter2D在opencv2/imgproc.hpp里
  45. //参数为(输入图像对象,输出图像对象,输入图像的depth(),kernel(算法之类的东西))
  46. //################################################################
  47. filter2D( src, dst1, src.depth(), kernel );
  48. t = ((double)getTickCount() - t)/getTickFrequency();
  49. cout << "Built-in filter2D time passed in seconds: " << t << endl;
  50. imshow( "Output", dst1 );
  51. waitKey();
  52. return 0;
  53. }
  54. void Sharpen(const Mat& myImage,Mat& Result)
  55. {
  56. CV_Assert(myImage.depth() == CV_8U); // accept only uchar images
  57. const int nChannels = myImage.channels();
  58. //###########################explanation##########################
  59. //用size和type就可以确定一个Mat的样子
  60. //################################################################
  61. Result.create(myImage.size(),myImage.type());
  62. for(int j = 1 ; j < myImage.rows-1; ++j)
  63. {
  64. const uchar* previous = myImage.ptr<uchar>(j - 1);
  65. const uchar* current = myImage.ptr<uchar>(j );
  66. const uchar* next = myImage.ptr<uchar>(j + 1);
  67. uchar* output = Result.ptr<uchar>(j);
  68. for(int i= nChannels;i < nChannels*(myImage.cols-1); ++i)
  69. {
  70. *output++ = saturate_cast<uchar>(5*current[i]
  71. -current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]);
  72. }
  73. }
  74. Result.row(0).setTo(Scalar(0));
  75. Result.row(Result.rows-1).setTo(Scalar(0));
  76. Result.col(0).setTo(Scalar(0));
  77. Result.col(Result.cols-1).setTo(Scalar(0));
  78. }


Operations with images

Input/Output

imread

  1. imread(filename, IMREAD_COLOR);

imwrite

  1. imwite( filename, img );


Basic operations with images

Accessing pixel intensity values

  1. Scalar intensity = img.at<uchar>(y, x);
  2. Scalar intensity = img.at<uchar>(Point(x, y));
  3. //3 channels
  4. Vec3b intensity = img.at<Vec3b>(y, x);
  5. uchar blue = intensity.val[0];
  6. uchar green = intensity.val[1];
  7. uchar red = intensity.val[2];
  8. //float
  9. Vec3f intensity = img.at<Vec3f>(y, x);
  10. float blue = intensity.val[0];
  11. float green = intensity.val[1];
  12. float red = intensity.val[2];
  13. //同样可以用该方法修改像素点的信息
  14. img.at<uchar>(y, x) = 128;
  15. //这里的Mat只有一列
  16. vector<Point2f> points{{3, 2},
  17. {2, 2},
  18. {89, 3}};
  19. //... fill the array
  20. Mat pointsMat = Mat(points);
  21. Point2f point = pointsMat.at<Point2f>(2, 0);
  22. cout << "x:" << point.x << " y:" << point.y << endl;

Memory management and reference counting

  1. Mat img = imread(argv[1]);
  2. Mat sobelx;
  3. Sobel(img, sobelx, CV_32F, 1, 0);


Primitive operations

  1. img = Scalar(0);
  2. Rect r(10, 10, 100, 100);
  3. Mat smallImg = img(r);
  4. //从类转换到结构体
  5. Mat img = imread("image.jpg");
  6. IplImage img1 = img;
  7. CvMat m = img;
  8. //切割图像
  9. Mat img = imread(argv[1]);
  10. Rect r(10, 500, 1000, 1000);
  11. Mat small_img = img(r);
  12. namedWindow("small_img", WINDOW_NORMAL);
  13. imshow("small_img", small_img);
  14. waitKey();
  15. //格式转换
  16. Mat img = imread("image.jpg"); // loading a 8UC3 image
  17. Mat grey;
  18. cvtColor(img, grey, COLOR_BGR2GRAY);
  19. //Change image type from 8UC1 to 32FC1:
  20. src.convertTo(dst, CV_32F);


Visualizing images

  1. Mat img = imread("image.jpg");
  2. Mat grey;
  3. cvtColor(img, grey, COLOR_BGR2GRAY);
  4. Mat sobelx;
  5. Sobel(grey, sobelx, CV_32F, 1, 0);
  6. double minVal, maxVal;
  7. minMaxLoc(sobelx, &minVal, &maxVal); //find minimum and maximum intensities
  8. Mat draw;
  9. sobelx.convertTo(draw, CV_8U, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal));
  10. namedWindow("image", WINDOW_AUTOSIZE);
  11. imshow("image", draw);
  12. waitKey();

Adding (blending) two images using OpenCV

source code

核心公式:


  1. #include "opencv2/imgcodecs.hpp"
  2. #include "opencv2/highgui.hpp"
  3. #include <iostream>
  4. using namespace cv;
  5. using namespace std;
  6. int main(void) {
  7. double alpha = 0.5;
  8. double beta;
  9. double input;
  10. Mat src1, src2, dst;
  11. cout << " Simple Linear Blender " << endl;
  12. cout << "-----------------------" << endl;
  13. cout << "* Enter alpha [0.0-1.0]: ";
  14. cin >> input;
  15. // We use the alpha provided by the user if it is between 0 and 1
  16. if (input >= 0 && input <= 1) { alpha = input; }
  17. src1 = imread("../img/phos.jpg");
  18. src2 = imread("../img/fall.jpg");
  19. //###########################explanation##########################
  20. //对图像进行切割达到同样大小
  21. //################################################################
  22. //Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
  23. Rect r(500, 500, 1000, 200);
  24. src1 = src1(r);
  25. src2 = src2(r);
  26. if (src1.empty()) {
  27. cout << "Error loading src1" << endl;
  28. return -1;
  29. }
  30. if (src2.empty()) {
  31. cout << "Error loading src2" << endl;
  32. return -1;
  33. }
  34. beta = (1.0 - alpha);
  35. addWeighted(src1, alpha, src2, beta, 0.0, dst);
  36. namedWindow("Linear Blend", WINDOW_NORMAL);
  37. imshow("Linear Blend", dst);
  38. waitKey(0);
  39. return 0;
  40. }



Changing the contrast and brightness of an image!

Image Processing

Pixel Transforms

Brightness and contrast adjustments


Code as

  1. #include "opencv2/imgcodecs.hpp"
  2. #include "opencv2/highgui.hpp"
  3. #include <iostream>
  4. using namespace std;
  5. using namespace cv;
  6. int main( int argc, char** argv )
  7. {
  8. double alpha = 1.0; /*< Simple contrast control */
  9. int beta = 0; /*< Simple brightness control */
  10. String imageName("../data/lena.jpg"); // by default
  11. if (argc > 1)
  12. {
  13. imageName = argv[1];
  14. }
  15. Mat image = imread( imageName );
  16. //###########################explanation##########################
  17. //得到和原图像矩阵同样规格的0矩阵
  18. //################################################################
  19. Mat new_image = Mat::zeros( image.size(), image.type() );
  20. cout << " Basic Linear Transforms " << endl;
  21. cout << "-------------------------" << endl;
  22. cout << "* Enter the alpha value [1.0-3.0]: "; cin >> alpha;
  23. cout << "* Enter the beta value [0-100]: "; cin >> beta;
  24. //###########################explanation##########################
  25. //对每一个像素点的每一个通道进行变换
  26. //saturate_cast用来保证每个变化后的是有效的
  27. //################################################################
  28. #if 0
  29. for (int y = 0; y < image.rows; y++) {
  30. for (int x = 0; x < image.cols; x++) {
  31. for (int c = 0; c < 3; c++) {
  32. new_image.at<Vec3b>(y, x)[c] =
  33. saturate_cast<uchar>(alpha * (image.at<Vec3b>(y, x)[c]) + beta);
  34. }
  35. }
  36. }
  37. #endif
  38. //###########################explanation##########################
  39. //另一种实现方式
  40. //################################################################
  41. image.convertTo(new_image, -1, alpha, beta);
  42. namedWindow("Original Image", WINDOW_AUTOSIZE);
  43. namedWindow("New Image", WINDOW_AUTOSIZE);
  44. imshow("Original Image", image);
  45. imshow("New Image", new_image);
  46. waitKey();
  47. return 0;
  48. }

Practical example

Brightness and contrast adjustments


调整了以后,会得到图中黑色部分的直方图,发现会使直方图整体右移,图像的明度提高了,右边就会出现一条很高的线(由饱和引起)


调整了以后,得到如下图中黑色部分,这时直方图被转移到了中间,图像的对比度提高了


由于引起的饱和,图像可能会丢失一些信息

Gamma correction


修正的核心函数:



由于修正是非线性的,所以每个像素点的修复程度都和本身属性决定

correction Plot


时,图像的明度会提高,直方图会右移,反之左移

Correct an underexposed image


先用修正


再用修正


直方图对比(从左到右依次为修正,原图,修正):


Gamma Correction Code

  1. Mat lookUpTable(1, 256, CV_8U);
  2. uchar* p = lookUpTable.ptr();
  3. for( int i = 0; i < 256; ++i)
  4. p[i] = saturate_cast<uchar>(pow(i / 255.0, gamma) * 255.0);
  5. Mat res = img.clone();
  6. LUT(img, lookUpTable, res);



Basic Drawing

OpenCV Theory

Point

  1. //2D像素点
  2. Point pt;
  3. pt.x = 10;
  4. pt.y = 8;
  5. //or
  6. Point pt = Point(10, 8);

Scalar

  1. //Blue = a, Green = b and Red = c 对于第四个参数,不需要用到的时候可以不用添加
  2. Scalar( a, b, c )

Code

  1. #include <opencv2/core.hpp>
  2. #include <opencv2/imgproc.hpp>
  3. #include <opencv2/highgui.hpp>
  4. #define w 400
  5. using namespace cv;
  6. void MyEllipse(Mat img, double angle);
  7. void MyFilledCircle(Mat img, Point center);
  8. void MyPolygon(Mat img);
  9. void MyLine(Mat img, Point start, Point end);
  10. int main(void) {
  11. //###########################explanation##########################
  12. //建立空白图像和窗口名称
  13. //################################################################
  14. char atom_window[] = "Drawing 1: Atom";
  15. char rook_window[] = "Drawing 2: Rook";
  16. Mat atom_image = Mat::zeros(w, w, CV_8UC3);
  17. Mat rook_image = Mat::zeros(w, w, CV_8UC3);
  18. //###########################explanation##########################
  19. //画图
  20. //################################################################
  21. MyEllipse(atom_image, 90);
  22. MyEllipse(atom_image, 0);
  23. MyEllipse(atom_image, 45);
  24. MyEllipse(atom_image, -45);
  25. MyFilledCircle(atom_image, Point(w / 2, w / 2));
  26. MyPolygon(rook_image);
  27. rectangle(rook_image,
  28. Point(0, 7 * w / 8),
  29. Point(w, w),
  30. Scalar(0, 255, 255),
  31. FILLED,
  32. LINE_8);
  33. MyLine(rook_image, Point(0, 15 * w / 16), Point(w, 15 * w / 16));
  34. MyLine(rook_image, Point(w / 4, 7 * w / 8), Point(w / 4, w));
  35. MyLine(rook_image, Point(w / 2, 7 * w / 8), Point(w / 2, w));
  36. MyLine(rook_image, Point(3 * w / 4, 7 * w / 8), Point(3 * w / 4, w));
  37. imshow(atom_window, atom_image);
  38. moveWindow(atom_window, 0, 200);
  39. imshow(rook_window, rook_image);
  40. moveWindow(rook_window, w, 200);
  41. waitKey(0);
  42. return (0);
  43. }
  44. void MyEllipse(Mat img, double angle) {
  45. int thickness = 2;
  46. int lineType = 8;
  47. ellipse(img,
  48. Point(w / 2, w / 2),
  49. Size(w / 4, w / 16),
  50. angle,
  51. 0,
  52. 360,
  53. Scalar(255, 0, 0),
  54. thickness,
  55. lineType);
  56. }
  57. void MyFilledCircle(Mat img, Point center) {
  58. circle(img,
  59. center,
  60. w / 32,
  61. Scalar(0, 0, 255),
  62. FILLED,
  63. LINE_8);
  64. }
  65. void MyPolygon(Mat img) {
  66. int lineType = LINE_8;
  67. Point rook_points[1][20];
  68. rook_points[0][0] = Point(w / 4, 7 * w / 8);
  69. rook_points[0][1] = Point(3 * w / 4, 7 * w / 8);
  70. rook_points[0][2] = Point(3 * w / 4, 13 * w / 16);
  71. rook_points[0][3] = Point(11 * w / 16, 13 * w / 16);
  72. rook_points[0][4] = Point(19 * w / 32, 3 * w / 8);
  73. rook_points[0][5] = Point(3 * w / 4, 3 * w / 8);
  74. rook_points[0][6] = Point(3 * w / 4, w / 8);
  75. rook_points[0][7] = Point(26 * w / 40, w / 8);
  76. rook_points[0][8] = Point(26 * w / 40, w / 4);
  77. rook_points[0][9] = Point(22 * w / 40, w / 4);
  78. rook_points[0][10] = Point(22 * w / 40, w / 8);
  79. rook_points[0][11] = Point(18 * w / 40, w / 8);
  80. rook_points[0][12] = Point(18 * w / 40, w / 4);
  81. rook_points[0][13] = Point(14 * w / 40, w / 4);
  82. rook_points[0][14] = Point(14 * w / 40, w / 8);
  83. rook_points[0][15] = Point(w / 4, w / 8);
  84. rook_points[0][16] = Point(w / 4, 3 * w / 8);
  85. rook_points[0][17] = Point(13 * w / 32, 3 * w / 8);
  86. rook_points[0][18] = Point(5 * w / 16, 13 * w / 16);
  87. rook_points[0][19] = Point(w / 4, 13 * w / 16);
  88. const Point *ppt[1] = {rook_points[0]};
  89. int npt[] = {20};
  90. fillPoly(img,
  91. ppt,
  92. npt,
  93. 1,
  94. Scalar(255, 255, 255),
  95. lineType);
  96. }
  97. void MyLine(Mat img, Point start, Point end) {
  98. int thickness = 2;
  99. int lineType = LINE_8;
  100. line(img,
  101. start,
  102. end,
  103. Scalar(0, 0, 0),
  104. thickness,
  105. lineType);
  106. }

ellipse

  1. CV_EXPORTS_W void ellipse(InputOutputArray img, Point center, Size axes,
  2. double angle, double startAngle, double endAngle,
  3. const Scalar& color, int thickness = 1,
  4. int lineType = LINE_8, int shift = 0);

Circle

  1. CV_EXPORTS_W void circle(InputOutputArray img, Point center, int radius,
  2. const Scalar& color, int thickness = 1,
  3. int lineType = LINE_8, int shift = 0);

line

  1. CV_EXPORTS_W void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color,
  2. int thickness = 1, int lineType = LINE_8, int shift = 0);



Random generator and text with OpenCV

Code

  1. #include <opencv2/core.hpp>
  2. #include <opencv2/imgproc.hpp>
  3. #include <opencv2/highgui.hpp>
  4. #include <iostream>
  5. #include <stdio.h>
  6. using namespace cv;
  7. /// Global Variables
  8. const int NUMBER = 100;
  9. const int DELAY = 5;
  10. const int window_width = 900;
  11. const int window_height = 600;
  12. int x_1 = -window_width/2;
  13. int x_2 = window_width*3/2;
  14. int y_1 = -window_width/2;
  15. int y_2 = window_width*3/2;
  16. /// Function headers
  17. static Scalar randomColor( RNG& rng );
  18. int Drawing_Random_Lines( Mat image, char* window_name, RNG rng );
  19. int Drawing_Random_Rectangles( Mat image, char* window_name, RNG rng );
  20. int Drawing_Random_Ellipses( Mat image, char* window_name, RNG rng );
  21. int Drawing_Random_Polylines( Mat image, char* window_name, RNG rng );
  22. int Drawing_Random_Filled_Polygons( Mat image, char* window_name, RNG rng );
  23. int Drawing_Random_Circles( Mat image, char* window_name, RNG rng );
  24. int Displaying_Random_Text( Mat image, char* window_name, RNG rng );
  25. int Displaying_Big_End( Mat image, char* window_name, RNG rng );
  26. /**
  27. * @function main
  28. */
  29. int main( void )
  30. {
  31. int c;
  32. /// Start creating a window
  33. char window_name[] = "Drawing_2 Tutorial";
  34. /// Also create a random object (RNG)
  35. RNG rng( 0xFFFFFFFF );
  36. /// Initialize a matrix filled with zeros
  37. Mat image = Mat::zeros( window_height, window_width, CV_8UC3 );
  38. /// Show it in a window during DELAY ms
  39. imshow( window_name, image );
  40. waitKey( DELAY );
  41. /// Now, let's draw some lines
  42. c = Drawing_Random_Lines(image, window_name, rng);
  43. if( c != 0 ) return 0;
  44. /// Go on drawing, this time nice rectangles
  45. c = Drawing_Random_Rectangles(image, window_name, rng);
  46. if( c != 0 ) return 0;
  47. /// Draw some ellipses
  48. c = Drawing_Random_Ellipses( image, window_name, rng );
  49. if( c != 0 ) return 0;
  50. /// Now some polylines
  51. c = Drawing_Random_Polylines( image, window_name, rng );
  52. if( c != 0 ) return 0;
  53. /// Draw filled polygons
  54. c = Drawing_Random_Filled_Polygons( image, window_name, rng );
  55. if( c != 0 ) return 0;
  56. /// Draw circles
  57. c = Drawing_Random_Circles( image, window_name, rng );
  58. if( c != 0 ) return 0;
  59. /// Display text in random positions
  60. c = Displaying_Random_Text( image, window_name, rng );
  61. if( c != 0 ) return 0;
  62. /// Displaying the big end!
  63. c = Displaying_Big_End( image, window_name, rng );
  64. if( c != 0 ) return 0;
  65. waitKey(0);
  66. return 0;
  67. }
  68. /// Function definitions
  69. /**
  70. * @function randomColor
  71. * @brief Produces a random color given a random object
  72. */
  73. static Scalar randomColor( RNG& rng )
  74. {
  75. int icolor = (unsigned) rng;
  76. return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );
  77. }
  78. /**
  79. * @function Drawing_Random_Lines
  80. */
  81. int Drawing_Random_Lines( Mat image, char* window_name, RNG rng )
  82. {
  83. Point pt1, pt2;
  84. for( int i = 0; i < NUMBER; i++ )
  85. {
  86. pt1.x = rng.uniform( x_1, x_2 );
  87. pt1.y = rng.uniform( y_1, y_2 );
  88. pt2.x = rng.uniform( x_1, x_2 );
  89. pt2.y = rng.uniform( y_1, y_2 );
  90. line( image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8 );
  91. imshow( window_name, image );
  92. if( waitKey( DELAY ) >= 0 )
  93. { return -1; }
  94. }
  95. return 0;
  96. }
  97. /**
  98. * @function Drawing_Rectangles
  99. */
  100. int Drawing_Random_Rectangles( Mat image, char* window_name, RNG rng )
  101. {
  102. Point pt1, pt2;
  103. int lineType = 8;
  104. int thickness = rng.uniform( -3, 10 );
  105. for( int i = 0; i < NUMBER; i++ )
  106. {
  107. pt1.x = rng.uniform( x_1, x_2 );
  108. pt1.y = rng.uniform( y_1, y_2 );
  109. pt2.x = rng.uniform( x_1, x_2 );
  110. pt2.y = rng.uniform( y_1, y_2 );
  111. rectangle( image, pt1, pt2, randomColor(rng), MAX( thickness, -1 ), lineType );
  112. imshow( window_name, image );
  113. if( waitKey( DELAY ) >= 0 )
  114. { return -1; }
  115. }
  116. return 0;
  117. }
  118. /**
  119. * @function Drawing_Random_Ellipses
  120. */
  121. int Drawing_Random_Ellipses( Mat image, char* window_name, RNG rng )
  122. {
  123. int lineType = 8;
  124. for ( int i = 0; i < NUMBER; i++ )
  125. {
  126. Point center;
  127. center.x = rng.uniform(x_1, x_2);
  128. center.y = rng.uniform(y_1, y_2);
  129. Size axes;
  130. axes.width = rng.uniform(0, 200);
  131. axes.height = rng.uniform(0, 200);
  132. double angle = rng.uniform(0, 180);
  133. ellipse( image, center, axes, angle, angle - 100, angle + 200,
  134. randomColor(rng), rng.uniform(-1,9), lineType );
  135. imshow( window_name, image );
  136. if( waitKey(DELAY) >= 0 )
  137. { return -1; }
  138. }
  139. return 0;
  140. }
  141. /**
  142. * @function Drawing_Random_Polylines
  143. */
  144. int Drawing_Random_Polylines( Mat image, char* window_name, RNG rng )
  145. {
  146. int lineType = 8;
  147. for( int i = 0; i< NUMBER; i++ )
  148. {
  149. Point pt[2][3];
  150. pt[0][0].x = rng.uniform(x_1, x_2);
  151. pt[0][0].y = rng.uniform(y_1, y_2);
  152. pt[0][1].x = rng.uniform(x_1, x_2);
  153. pt[0][1].y = rng.uniform(y_1, y_2);
  154. pt[0][2].x = rng.uniform(x_1, x_2);
  155. pt[0][2].y = rng.uniform(y_1, y_2);
  156. pt[1][0].x = rng.uniform(x_1, x_2);
  157. pt[1][0].y = rng.uniform(y_1, y_2);
  158. pt[1][1].x = rng.uniform(x_1, x_2);
  159. pt[1][1].y = rng.uniform(y_1, y_2);
  160. pt[1][2].x = rng.uniform(x_1, x_2);
  161. pt[1][2].y = rng.uniform(y_1, y_2);
  162. const Point* ppt[2] = {pt[0], pt[1]};
  163. int npt[] = {3, 3};
  164. polylines(image, ppt, npt, 2, true, randomColor(rng), rng.uniform(1,10), lineType);
  165. imshow( window_name, image );
  166. if( waitKey(DELAY) >= 0 )
  167. { return -1; }
  168. }
  169. return 0;
  170. }
  171. /**
  172. * @function Drawing_Random_Filled_Polygons
  173. */
  174. int Drawing_Random_Filled_Polygons( Mat image, char* window_name, RNG rng )
  175. {
  176. int lineType = 8;
  177. for ( int i = 0; i < NUMBER; i++ )
  178. {
  179. Point pt[2][3];
  180. pt[0][0].x = rng.uniform(x_1, x_2);
  181. pt[0][0].y = rng.uniform(y_1, y_2);
  182. pt[0][1].x = rng.uniform(x_1, x_2);
  183. pt[0][1].y = rng.uniform(y_1, y_2);
  184. pt[0][2].x = rng.uniform(x_1, x_2);
  185. pt[0][2].y = rng.uniform(y_1, y_2);
  186. pt[1][0].x = rng.uniform(x_1, x_2);
  187. pt[1][0].y = rng.uniform(y_1, y_2);
  188. pt[1][1].x = rng.uniform(x_1, x_2);
  189. pt[1][1].y = rng.uniform(y_1, y_2);
  190. pt[1][2].x = rng.uniform(x_1, x_2);
  191. pt[1][2].y = rng.uniform(y_1, y_2);
  192. const Point* ppt[2] = {pt[0], pt[1]};
  193. int npt[] = {3, 3};
  194. fillPoly( image, ppt, npt, 2, randomColor(rng), lineType );
  195. imshow( window_name, image );
  196. if( waitKey(DELAY) >= 0 )
  197. { return -1; }
  198. }
  199. return 0;
  200. }
  201. /**
  202. * @function Drawing_Random_Circles
  203. */
  204. int Drawing_Random_Circles( Mat image, char* window_name, RNG rng )
  205. {
  206. int lineType = 8;
  207. for (int i = 0; i < NUMBER; i++)
  208. {
  209. Point center;
  210. center.x = rng.uniform(x_1, x_2);
  211. center.y = rng.uniform(y_1, y_2);
  212. circle( image, center, rng.uniform(0, 300), randomColor(rng),
  213. rng.uniform(-1, 9), lineType );
  214. imshow( window_name, image );
  215. if( waitKey(DELAY) >= 0 )
  216. { return -1; }
  217. }
  218. return 0;
  219. }
  220. /**
  221. * @function Displaying_Random_Text
  222. */
  223. int Displaying_Random_Text( Mat image, char* window_name, RNG rng )
  224. {
  225. int lineType = 8;
  226. for ( int i = 1; i < NUMBER; i++ )
  227. {
  228. Point org;
  229. org.x = rng.uniform(x_1, x_2);
  230. org.y = rng.uniform(y_1, y_2);
  231. putText( image, "Testing text rendering", org, rng.uniform(0,8),
  232. rng.uniform(0,100)*0.05+0.1, randomColor(rng), rng.uniform(1, 10), lineType);
  233. imshow( window_name, image );
  234. if( waitKey(DELAY) >= 0 )
  235. { return -1; }
  236. }
  237. return 0;
  238. }
  239. /**
  240. * @function Displaying_Big_End
  241. */
  242. int Displaying_Big_End( Mat image, char* window_name, RNG )
  243. {
  244. Size textsize = getTextSize("OpenCV forever!", FONT_HERSHEY_COMPLEX, 3, 5, 0);
  245. Point org((window_width - textsize.width)/2, (window_height - textsize.height)/2);
  246. int lineType = 8;
  247. Mat image2;
  248. for( int i = 0; i < 255; i += 2 )
  249. {
  250. image2 = image - Scalar::all(i);
  251. putText( image2, "OpenCV forever!", org, FONT_HERSHEY_COMPLEX, 3,
  252. Scalar(i, i, 255), 5, lineType );
  253. imshow( window_name, image2 );
  254. if( waitKey(DELAY) >= 0 )
  255. { return -1; }
  256. }
  257. return 0;
  258. }































添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注