1 //! [head] 2 #include <stdio.h> 3 #include <iostream> 4 5 #include <opencv2/core/core.hpp> 6 #include <opencv2/imgproc/imgproc.hpp> 7 #include "opencv2/imgcodecs.hpp" 8 #include <opencv2/highgui/highgui.hpp> 9 #include <opencv2/core/utility.hpp> 10 11 using namespace cv; // The new C++ interface API is inside this namespace. Import it. 12 using namespace std; 13 //! [head] 14 15 static void help( char* progName) 16 { 17 cout << endl << progName 18 << " shows how to use cv::Mat and IplImages together (converting back and forth)." << endl 19 << "Also contains example for image read, spliting the planes, merging back and " << endl 20 << " color conversion, plus iterating through pixels. " << endl 21 << "Usage:" << endl 22 << progName << " [image-name Default: ../data/lena.jpg]" << endl << endl; 23 } 24 25 //! [start] 26 // comment out the define to use only the latest C++ API 27 #define DEMO_MIXED_API_USE 28 29 #ifdef DEMO_MIXED_API_USE 30 # include <opencv2/highgui/highgui_c.h> 31 # include <opencv2/imgcodecs/imgcodecs_c.h> 32 #endif 33 34 int main( int argc, char** argv ) 35 { 36 help(argv[0]); 37 const char* imagename = argc > 1 ? argv[1] : "../data/lena.jpg"; 38 39 #ifdef DEMO_MIXED_API_USE 40 Ptr<IplImage> IplI(cvLoadImage(imagename)); // Ptr<T> is a safe ref-counting pointer class 41 if(!IplI) 42 { 43 cerr << "Can not load image " << imagename << endl; 44 return -1; 45 } 46 Mat I = cv::cvarrToMat(IplI); // Convert to the new style container. Only header created. Image not copied. 47 #else 48 Mat I = imread(imagename); // the newer cvLoadImage alternative, MATLAB-style function 49 if( I.empty() ) // same as if( !I.data ) 50 { 51 cerr << "Can not load image " << imagename << endl; 52 return -1; 53 } 54 #endif 55 //! [start] 56 57 //! [new] 58 // convert image to YUV color space. The output image will be created automatically. 59 Mat I_YUV; 60 cvtColor(I, I_YUV, COLOR_BGR2YCrCb); 61 62 vector<Mat> planes; // Use the STL's vector structure to store multiple Mat objects 63 split(I_YUV, planes); // split the image into separate color planes (Y U V) 64 //! [new] 65 66 #if 1 // change it to 0 if you want to see a blurred and noisy version of this processing 67 //! [scanning] 68 // Mat scanning 69 // Method 1. process Y plane using an iterator 70 MatIterator_<uchar> it = planes[0].begin<uchar>(), it_end = planes[0].end<uchar>(); 71 for(; it != it_end; ++it) 72 { 73 double v = *it * 1.7 + rand()%21 - 10; 74 *it = saturate_cast<uchar>(v*v/255); 75 } 76 77 for( int y = 0; y < I_YUV.rows; y++ ) 78 { 79 // Method 2. process the first chroma plane using pre-stored row pointer. 80 uchar* Uptr = planes[1].ptr<uchar>(y); 81 for( int x = 0; x < I_YUV.cols; x++ ) 82 { 83 Uptr[x] = saturate_cast<uchar>((Uptr[x]-128)/2 + 128); 84 85 // Method 3. process the second chroma plane using individual element access 86 uchar& Vxy = planes[2].at<uchar>(y, x); 87 Vxy = saturate_cast<uchar>((Vxy-128)/2 + 128); 88 } 89 } 90 //! [scanning] 91 92 #else 93 94 //! [noisy] 95 Mat noisyI(I.size(), CV_8U); // Create a matrix of the specified size and type 96 97 // Fills the matrix with normally distributed random values (around number with deviation off). 98 // There is also randu() for uniformly distributed random number generation 99 randn(noisyI, Scalar::all(128), Scalar::all(20)); 100 101 // blur the noisyI a bit, kernel size is 3x3 and both sigma's are set to 0.5 102 GaussianBlur(noisyI, noisyI, Size(3, 3), 0.5, 0.5); 103 104 const double brightness_gain = 0; 105 const double contrast_gain = 1.7; 106 107 #ifdef DEMO_MIXED_API_USE 108 // To pass the new matrices to the functions that only work with IplImage or CvMat do: 109 // step 1) Convert the headers (tip: data will not be copied). 110 // step 2) call the function (tip: to pass a pointer do not forget unary "&" to form pointers) 111 112 IplImage cv_planes_0 = planes[0], cv_noise = noisyI; 113 cvAddWeighted(&cv_planes_0, contrast_gain, &cv_noise, 1, -128 + brightness_gain, &cv_planes_0); 114 #else 115 addWeighted(planes[0], contrast_gain, noisyI, 1, -128 + brightness_gain, planes[0]); 116 #endif 117 118 const double color_scale = 0.5; 119 // Mat::convertTo() replaces cvConvertScale. 120 // One must explicitly specify the output matrix type (we keep it intact - planes[1].type()) 121 planes[1].convertTo(planes[1], planes[1].type(), color_scale, 128*(1-color_scale)); 122 123 // alternative form of cv::convertScale if we know the datatype at compile time ("uchar" here). 124 // This expression will not create any temporary arrays ( so should be almost as fast as above) 125 planes[2] = Mat_<uchar>(planes[2]*color_scale + 128*(1-color_scale)); 126 127 // Mat::mul replaces cvMul(). Again, no temporary arrays are created in case of simple expressions. 128 planes[0] = planes[0].mul(planes[0], 1./255); 129 //! [noisy] 130 #endif 131 132 133 //! [end] 134 merge(planes, I_YUV); // now merge the results back 135 cvtColor(I_YUV, I, COLOR_YCrCb2BGR); // and produce the output RGB image 136 137 namedWindow("image with grain", WINDOW_AUTOSIZE); // use this to create images 138 139 #ifdef DEMO_MIXED_API_USE 140 // this is to demonstrate that I and IplI really share the data - the result of the above 141 // processing is stored in I and thus in IplI too. 142 cvShowImage("image with grain", IplI); 143 #else 144 imshow("image with grain", I); // the new MATLAB style function show 145 #endif 146 //! [end] 147 waitKey(); 148 149 // Tip: No memory freeing is required! 150 // All the memory will be automatically released by the Vector<>, Mat and Ptr<> destructor. 151 return 0; 152 } 153