diff --git a/doc/tutorials/core/basic_linear_transform/basic_linear_transform.markdown b/doc/tutorials/core/basic_linear_transform/basic_linear_transform.markdown index 803de71acb..26a5152e63 100644 --- a/doc/tutorials/core/basic_linear_transform/basic_linear_transform.markdown +++ b/doc/tutorials/core/basic_linear_transform/basic_linear_transform.markdown @@ -150,7 +150,7 @@ We observe that @ref cv::Mat::zeros returns a Matlab-style zero initializer base Notice the following (**C++ code only**): - To access each pixel in the images we are using this syntax: *image.at\(y,x)[c]* - where *y* is the row, *x* is the column and *c* is R, G or B (0, 1 or 2). + where *y* is the row, *x* is the column and *c* is B, G or R (0, 1 or 2). - Since the operation \f$\alpha \cdot p(i,j) + \beta\f$ can give values out of range or not integers (if \f$\alpha\f$ is float), we use cv::saturate_cast to make sure the values are valid. @@ -220,12 +220,12 @@ gamma correction. ### Brightness and contrast adjustments Increasing (/ decreasing) the \f$\beta\f$ value will add (/ subtract) a constant value to every pixel. Pixel values outside of the [0 ; 255] -range will be saturated (i.e. a pixel value higher (/ lesser) than 255 (/ 0) will be clamp to 255 (/ 0)). +range will be saturated (i.e. a pixel value higher (/ lesser) than 255 (/ 0) will be clamped to 255 (/ 0)). ![In light gray, histogram of the original image, in dark gray when brightness = 80 in Gimp](images/Basic_Linear_Transform_Tutorial_hist_beta.png) The histogram represents for each color level the number of pixels with that color level. A dark image will have many pixels with -low color value and thus the histogram will present a peak in his left part. When adding a constant bias, the histogram is shifted to the +low color value and thus the histogram will present a peak in its left part. When adding a constant bias, the histogram is shifted to the right as we have added a constant bias to all the pixels. The \f$\alpha\f$ parameter will modify how the levels spread. If \f$ \alpha < 1 \f$, the color levels will be compressed and the result diff --git a/doc/tutorials/core/how_to_scan_images/how_to_scan_images.markdown b/doc/tutorials/core/how_to_scan_images/how_to_scan_images.markdown index 0140e14058..d41844c4f7 100644 --- a/doc/tutorials/core/how_to_scan_images/how_to_scan_images.markdown +++ b/doc/tutorials/core/how_to_scan_images/how_to_scan_images.markdown @@ -10,7 +10,7 @@ Goal We'll seek answers for the following questions: - How to go through each and every pixel of an image? -- How is OpenCV matrix values stored? +- How are OpenCV matrix values stored? - How to measure the performance of our algorithm? - What are lookup tables and why use them? @@ -45,13 +45,13 @@ operation. In case of the *uchar* system this is 256 to be exact. 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. -Its strength lies that we do not need to make the calculation, we just need to read the result. +Its strength is that we do not need to make the calculation, we just need to read the result. -Our test case program (and the sample presented here) will do the following: read in a console line -argument image (that may be either color or gray scale - console line argument too) and apply the -reduction with the given console line argument integer value. In OpenCV, at the moment there are +Our test case program (and the code sample below) will do the following: read in an image passed +as a command line argument (it may be either color or grayscale) and apply the reduction +with the given command line argument integer value. In OpenCV, at the moment there are three major ways of going through an image pixel by pixel. To make things a little more interesting -will make the scanning for each image using all of these methods, and print out how long it took. +we'll make the scanning of the image using each of these methods, and print out how long it took. You can download the full source code [here ](https://github.com/opencv/opencv/tree/3.4/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp) or look it up in @@ -59,7 +59,7 @@ the samples directory of OpenCV at the cpp tutorial code for the core section. I @code{.bash} how_to_scan_images imageName.jpg intValueToReduce [G] @endcode -The final argument is optional. If given the image will be loaded in gray scale format, otherwise +The final argument is optional. If given the image will be loaded in grayscale format, otherwise the BGR color space is used. The first thing is to calculate the lookup table. @snippet how_to_scan_images.cpp dividewith @@ -71,8 +71,8 @@ No OpenCV specific stuff here. Another issue is how do we measure time? Well OpenCV offers two simple functions to achieve this cv::getTickCount() and cv::getTickFrequency() . 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. So to measure in seconds the number of time -elapsed between two operations is easy as: +many times your CPU emits a tick during a second. So, measuring amount of time elapsed between +two operations is as easy as: @code{.cpp} double t = (double)getTickCount(); // do something ... @@ -85,8 +85,8 @@ How is the image matrix stored in memory? ----------------------------------------- As you could already read in my @ref tutorial_mat_the_basic_image_container tutorial the size of the matrix -depends on the color system used. More accurately, it depends from the number of channels used. In -case of a gray scale image we have something like: +depends on the color system used. More accurately, it depends on the number of channels used. In +case of a grayscale image we have something like: ![](tutorial_how_matrix_stored_1.png) @@ -117,12 +117,12 @@ three channels so we need to pass through three times more items in each row. There's another way of this. 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 -continuous we can use this to go through the whole data pointer. In case of a gray scale image this +continuous we can use this to go through the whole data pointer. In case of a grayscale image this would look like: @code{.cpp} uchar* p = I.data; -for( unsigned int i =0; i < ncol*nrows; ++i) +for( unsigned int i = 0; i < ncol*nrows; ++i) *p++ = table[*p]; @endcode You would get the same result. However, this code is a lot harder to read later on. It gets even @@ -135,7 +135,7 @@ The iterator (safe) method 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 +considered a safer way as it takes over these tasks from the user. All you need to do is to ask the begin and the end of the image matrix and then just increase the begin iterator until you reach the end. To acquire the value *pointed* by the iterator use the \* operator (add it before it). @@ -152,17 +152,17 @@ On-the-fly address calculation with reference returning The final method isn't recommended for scanning. 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. During our earlier scanning methods you could already observe that is important through +to access. During our earlier scanning methods you could already notice that it is important through what type we are looking at the image. It's no different here as you need to manually specify what -type to use at the automatic lookup. You can observe this in case of the gray scale images for the +type to use at the automatic lookup. You can observe this in case of the grayscale images for the following source code (the usage of the + cv::Mat::at() function): @snippet how_to_scan_images.cpp scan-random -The functions takes your input type and coordinates and calculates on the fly the address of the +The function takes your input type and coordinates and calculates the address of the queried item. Then returns a reference to that. This may be a constant when you *get* the value and -non-constant when you *set* the value. As a safety step in **debug mode only**\* there is performed -a check that your input coordinates are valid and does exist. If this isn't the case you'll get a +non-constant when you *set* the value. As a safety step in **debug mode only**\* there is a check +performed that your input coordinates are valid and do exist. If this isn't the case you'll get a nice output message of this on the standard error output stream. Compared to the efficient way in release mode the only difference in using this is that for every element of the image you'll get a new row pointer for what we use the C operator[] to acquire the column element. @@ -173,7 +173,7 @@ OpenCV has a cv::Mat_ data type. It's the same as Mat with the extra need that a you need to specify the data type through what to look at the data matrix, however in return you can use the operator() for fast access of items. To make things even better this is easily convertible from and to the usual cv::Mat data type. A sample usage of this you can see in case of the -color images of the upper function. Nevertheless, it's important to note that the same operation +color images of the function above. Nevertheless, it's important to note that the same operation (with the same runtime speed) could have been done with the cv::Mat::at function. It's just a less to write for the lazy programmer trick. @@ -195,7 +195,7 @@ Finally call the function (I is our input image and J the output one): Performance Difference ---------------------- -For the best result compile the program and run it on your own speed. To make the differences more +For the best result compile the program and run it yourself. To make the differences more clear, I've used a quite large (2560 X 1600) image. The performance presented here are for color images. For a more accurate value I've averaged the value I got from the call of the function for hundred times. diff --git a/doc/tutorials/core/mat-mask-operations/mat_mask_operations.markdown b/doc/tutorials/core/mat-mask-operations/mat_mask_operations.markdown index bd74267f54..97e4052a94 100644 --- a/doc/tutorials/core/mat-mask-operations/mat_mask_operations.markdown +++ b/doc/tutorials/core/mat-mask-operations/mat_mask_operations.markdown @@ -4,7 +4,7 @@ Mask operations on matrices {#tutorial_mat_mask_operations} @prev_tutorial{tutorial_how_to_scan_images} @next_tutorial{tutorial_mat_operations} -Mask operations on matrices are quite simple. The idea is that we recalculate each pixels value in +Mask operations on matrices are quite simple. The idea is that we recalculate each pixel's value in an image according to a mask matrix (also known as kernel). This mask holds values that will adjust how much influence neighboring pixels (and the current pixel) have on the new pixel value. From a mathematical point of view we make a weighted average, with our specified values. @@ -12,7 +12,7 @@ mathematical point of view we make a weighted average, with our specified values Our test case ------------- -Let us consider the issue of an image contrast enhancement method. Basically we want to apply for +Let's consider the issue of an image contrast enhancement method. Basically we want to apply for every pixel of the image the following formula: \f[I(i,j) = 5*I(i,j) - [ I(i-1,j) + I(i+1,j) + I(i,j-1) + I(i,j+1)]\f]\f[\iff I(i,j)*M, \text{where } @@ -144,7 +144,7 @@ Then we apply the sum and put the new value in the Result matrix. The filter2D function --------------------- -Applying such filters are so common in image processing that in OpenCV there exist a function that +Applying such filters are so common in image processing that in OpenCV there is a function that will take care of applying the mask (also called a kernel in some places). For this you first need to define an object that holds the mask: diff --git a/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.markdown b/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.markdown index 882b7a4a0b..f6a1a0a4fb 100644 --- a/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.markdown +++ b/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.markdown @@ -61,7 +61,7 @@ The last thing we want to do is further decrease the speed of your program by ma copies of potentially *large* images. To tackle this issue OpenCV uses a reference counting system. The idea is that each *Mat* object has -its own header, however the matrix may be shared between two instance of them by having their matrix +its own header, however a matrix may be shared between two *Mat* objects by having their matrix pointers point to the same address. Moreover, the copy operators **will only copy the headers** and the pointer to the large matrix, not the data itself. @@ -74,32 +74,32 @@ Mat B(A); // Use the copy constructor C = A; // Assignment operator @endcode -All the above objects, in the end, point to the same single data matrix. Their headers are -different, however, and making a modification using any of them will affect all the other ones as -well. In practice the different objects just provide different access method to the same underlying -data. Nevertheless, their header parts are different. The real interesting part is that you can -create headers which refer to only a subsection of the full data. For example, to create a region of -interest (*ROI*) in an image you just create a new header with the new boundaries: +All the above objects, in the end, point to the same single data matrix and making a modification +using any of them will affect all the other ones as well. In practice the different objects just +provide different access methods to the same underlying data. Nevertheless, their header parts are +different. The real interesting part is that you can create headers which refer to only a subsection +of the full data. For example, to create a region of interest (*ROI*) in an image you just create +a new header with the new boundaries: @code{.cpp} Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle Mat E = A(Range::all(), Range(1,3)); // using row and column boundaries @endcode -Now you may ask if the matrix itself may belong to multiple *Mat* objects who takes responsibility +Now you may ask -- if the matrix itself may belong to multiple *Mat* objects who takes responsibility for cleaning it up when it's no longer needed. The short answer is: the last object that used it. This is handled by using a reference counting mechanism. Whenever somebody copies a header of a -*Mat* object, a counter is increased for the matrix. Whenever a header is cleaned this counter is -decreased. When the counter reaches zero the matrix too is freed. Sometimes you will want to copy -the matrix itself too, so OpenCV provides the @ref cv::Mat::clone() and @ref cv::Mat::copyTo() functions. +*Mat* object, a counter is increased for the matrix. Whenever a header is cleaned, this counter +is decreased. When the counter reaches zero the matrix is freed. Sometimes you will want to copy +the matrix itself too, so OpenCV provides @ref cv::Mat::clone() and @ref cv::Mat::copyTo() functions. @code{.cpp} Mat F = A.clone(); Mat G; A.copyTo(G); @endcode -Now modifying *F* or *G* will not affect the matrix pointed by the *Mat* header. What you need to +Now modifying *F* or *G* will not affect the matrix pointed by the *A*'s header. What you need to remember from all this is that: - Output image allocation for OpenCV functions is automatic (unless specified otherwise). -- You do not need to think about memory management with OpenCVs C++ interface. +- You do not need to think about memory management with OpenCV's C++ interface. - The assignment operator and the copy constructor only copies the header. - The underlying matrix of an image may be copied using the @ref cv::Mat::clone() and @ref cv::Mat::copyTo() functions. @@ -109,7 +109,7 @@ Storing methods This is about how you store the pixel values. You can select the color space and the data type used. The color space refers to how we combine color components in order to code a given color. The -simplest one is the gray scale where the colors at our disposal are black and white. The combination +simplest one is the grayscale where the colors at our disposal are black and white. The combination of these allows us to create many shades of gray. For *colorful* ways we have a lot more methods to choose from. Each of them breaks it down to three @@ -121,15 +121,15 @@ added. There are, however, many other color systems each with their own advantages: - RGB is the most common as our eyes use something similar, however keep in mind that OpenCV standard display - system composes colors using the BGR color space (a switch of the red and blue channel). + system composes colors using the BGR color space (red and blue channels are swapped places). - The HSV and HLS decompose colors into their hue, saturation and value/luminance components, which is a more natural way for us to describe colors. You might, for example, dismiss the last component, making your algorithm less sensible to the light conditions of the input image. - YCrCb is used by the popular JPEG image format. -- CIE L\*a\*b\* is a perceptually uniform color space, which comes handy if you need to measure +- CIE L\*a\*b\* is a perceptually uniform color space, which comes in handy if you need to measure the *distance* of a given color to another color. -Each of the building components has their own valid domains. This leads to the data type used. How +Each of the building components has its own valid domains. This leads to the data type used. How we store a component defines the control we have over its domain. The smallest data type possible is *char*, which means one byte or 8 bits. This may be unsigned (so can store values from 0 to 255) or signed (values from -127 to +127). Although in case of three components this already gives 16 @@ -165,8 +165,8 @@ object in multiple ways: CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number] @endcode For instance, *CV_8UC3* means we use unsigned char types that are 8 bit long and each pixel has - three of these to form the three channels. This are predefined for up to four channel numbers. The - @ref cv::Scalar is four element short vector. Specify this and you can initialize all matrix + three of these to form the three channels. There are types predefined for up to four channels. The + @ref cv::Scalar is four element short vector. Specify it and you can initialize all matrix points with a custom value. If you need more you can create the type with the upper macro, setting the channel number in parenthesis as you can see below. @@ -210,7 +210,7 @@ object in multiple ways: @note You can fill out a matrix with random values using the @ref cv::randu() function. You need to - give the lower and upper value for the random values: + give a lower and upper limit for the random values: @snippet mat_the_basic_image_container.cpp random diff --git a/modules/core/include/opencv2/core/saturate.hpp b/modules/core/include/opencv2/core/saturate.hpp index 118599f8f9..36d312154f 100644 --- a/modules/core/include/opencv2/core/saturate.hpp +++ b/modules/core/include/opencv2/core/saturate.hpp @@ -74,8 +74,6 @@ namespace cv the floating-point value is first rounded to the nearest integer and then clipped if needed (when the target type is 8- or 16-bit). - This operation is used in the simplest or most complex image processing functions in OpenCV. - @param v Function parameter. @sa add, subtract, multiply, divide, Mat::convertTo */