This small experiment completes the following five functions:
1: Use TrackBar to implement button function (OpenCV without the button, without QT I can only use Trackerbar to achieve visual operation);
2: Calculate and draw the histogram;
3:histogram equalization;
4: Achieve lomography effect;
5: Achieve cartoonize effect.
3 in order to equalize a color image, we can the image of the HSV or YCRCB format for each channel to be balanced, where we have the image YCRCB format of the Y Channel equalization. Split the matrix of the different channels of the YCRCB format image, then equalizehist the y channel, then merge the channel, and finally convert the image to RGB image.
The implementation of the Lomography effect in 4 is divided into two steps. The red channel is first LUT operation to realize the curve transformation, the transformation formula is as follows:
The effect of the formula is to enhance the contrast of the image
Next to the image to increase the dark Halo (Dark Halo), the last multiply operation to achieve results.
5 to achieve cartoonize effect, the first step to detect the edge of the image, of course, the first to noise reduction processing, detection of the edge of the expansion operation after the extension of the edge. Finally, the result of multiply operation of the edge image and color image is realized.
See the code specifically.
OpenCV includes #include "opencv2/core/utility.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp"
using namespace CV;
using namespace Std;
Mat img;
void Showhisto (int state, void* userData);
void equalize (int state, void* userData);
void Lomo (int state, void* userData);
void cartoon (int state, void* userData); OpenCV command line parser functions//Keys accecpted by command line parser const char* Keys = {' {help H usage? | | Print this message} "" {@image | |
Image to Process} "};
char* trackbar_name = "mode 1-4";
char* window_name = "Mode Table";
int ModeL = 0;
int Modeh = 4;
void Switchmode (int pos, void*) {if (pos = 1) {showhisto (0, 0);
} if (pos = = 2) {equalize (0, 0);
} if (pos = = 3) {lomo (0, 0);
} if (pos = = 4) {cartoon (0, 0);
int main (int argc, const char** argv) {/* Commandlineparser parser (ARGC, argv, keys); Parser.about ("Chapter 4").
Phototool v1.0.0 "); If requires help show if (Parser.has ("Help")) {ParseR.printmessage ();
return 0;
String imgfile = parser.get<string> (0);
Check if params are correctly parsed in his variables if (!parser.check ()) {parser.printerrors ();
return 0;
*///Load image to process img = Imread ("e:/vs2013/face/xuelian/jpg/1.jpg");
if (!img.data) {return-1;
}//Create window Namedwindow (window_name);
Create UI Buttons/* Createbutton ("show histogram", Showhistocallback, NULL, Qt_push_button, 0);
Createbutton ("Equalize histogram", Equalizecallback, NULL, Qt_push_button, 0);
Createbutton ("Lomography effect", Lomocallback, NULL, Qt_push_button, 0);
Createbutton ("Cartonize effect", Cartooncallback, NULL, Qt_push_button, 0); * * Createtrackbar (Trackbar_name, Window_name, &model, Modeh, switchmode);//Use TrackBar to implement button feature//Show image//i
Mshow ("Input", IMG);
Waitkey (0);
return 0;
} void Showhisto (int state, void* userData) {//split into 3 single channel images (B, G and R) vector<mat> BGR;
Split (IMG, BGR); Set bin number, rowNumber of sub intervals int numbins = 256;
Set the range of pixel values (mentioned above, between 0 and 255) float range[] = {0, 255};
Const float* Histrange = {range};
Create a matrix that stores histograms Mat b_hist, g_hist, r_hist; Compute histogram/* Bgr[i]: Input Array (or set of array) 1: Number of input arrays (we use a single channel image here, we can also input array set) 0: The Channel (dim) Index that needs to be counted, where we just count the grayscale (and each array is a single channel) so as long as
Just write 0. Mat (): The Mask (0 indicates that the pixel is ignored) and, if not defined, does not use the mask b_hist: The Matrix 1 of the histogram is stored: the vertical graph Dimension Numbins: The number of bins per dimension Histrange: The range of values per dimension * *
Calchist (&bgr[0], 1, 0, Mat (), b_hist, 1, &numbins, &histrange);
Calchist (&bgr[1], 1, 0, Mat (), g_hist, 1, &numbins, &histrange);
Calchist (&bgr[2], 1, 0, Mat (), r_hist, 1, &numbins, &histrange);
Draw the histogram//We go to Draw lines for each channel int width = 512;
int height = 300; int binstep = Cvround ((float) width/(float) numbins),//The number of a double is rounded and returns an integer//Create image with gray base Mat hi
Stimage (height, width, cv_8uc3, Scalar (20, 20, 20)); Normalize the histograms to height of image//histogram normalization to range [0, hisTimage.rows]/* r_hist: Input array r_hist: Normalized output Array (supports in-situ calculations) 0 and histimage.rows: Here, they are the threshold r_hist after normalization Norm_minmax: Normalized side
Method (the methods specified in the example to scale the value to the specified range above) * * Normalize (b_hist, b_hist, 0, height, norm_minmax);
Normalize (g_hist, g_hist, 0, height, norm_minmax);
Normalize (r_hist, r_hist, 0, height, norm_minmax); for (int i = 1; i< numbins. i++) {//line (Mat img, point Start, point end) line (Histimage, point (binstep*) (I-
1), Height-cvround (b_hist.at<float> (i-1)), point (binstep* (i), Height-cvround (b_hist.at<float> (i))),
Scalar (255, 0, 0)); Line (Histimage, point (binstep* i-1), Height-cvround (g_hist.at<float> (i-1)), point (binstep* (i), height-
Cvround (g_hist.at<float> (i))), Scalar (0, 255, 0)); Line (Histimage, point (binstep* i-1), Height-cvround (r_hist.at<float> (i-1)), point (binstep* (i), height-
Cvround (r_hist.at<float> (i))), Scalar (0, 0, 255));
} imshow ("Histogram", histimage); } void Equalize (int state, void* userData) {Mat result;
Convert BGR image to YCbCr Mat YCRCB;
Cvtcolor (IMG, YCRCB, COLOR_BGR2YCRCB);
Split image into channels vector<mat> channels;
Split (YCRCB, Channels);
Equalize the Y channel only Equalizehist (Channels[0], channels[0]);
Merge the result channels the merge (channels, YCRCB);
Convert color YCRCB to BGR cvtcolor (YCRCB, result, COLOR_YCRCB2BGR);
Show Image Imshow ("equalized", result);
} void Lomo (int state, void* userData) {Mat result;
Const double exponential_e = STD::EXP (1.0);
Create Lookup table for color curve effect Mat lut (1, 256, CV_8UC1);//Create a 256-element mapping table for (int i = 0; i<256; i++)
{Float x = (float) i/256.0; Lut.at<uchar> (i) = Cvround (256 * (1/(1 + POW (exponential_e,-((x-0.5)/0.1)))//pow (Inputarray src, double p,
Outputarray DST)}//Split the image channels and apply curve transform only to red channel vector<mat>;
Split (IMG, BGR); LUT (bgr[2], LUT, bgr[2]);
Merge result merge (BGR, result);
Create image for Halo dark Mat halo (Img.rows, Img.cols, CV_32FC3, Scalar (0.3, 0.3, 0.3));
Create Circle Circle (Halo, point (IMG.COLS/2, IMG.ROWS/2), IMG.COLS/3, Scalar (1, 1, 1),-1);
Blur (Halo, Halo, Size (IMG.COLS/3, IMG.COLS/3));
Convert the result to float to allow multiply by 1 factor Mat RESULTF;
Result.convertto (RESULTF, CV_32FC3);
Multiply our result with Halo Multiply (RESULTF, Halo, RESULTF);
Convert to 8 bits Resultf.convertto (result, CV_8UC3);
Show result Imshow ("Lomo Effect", result); } void cartoon (int state, void* userData) {/** EDGES **///Apply median filter to remove possible noise Mat
N
Medianblur (IMG, Imgmedian, 7);
Detect edges with canny Mat imgcanny;
Canny (Imgmedian, Imgcanny, 50, 150);
Dilate the edges makes intermittent edges connected Mat kernel = getstructuringelement (Morph_rect, Size (2, 2));
Dilate (Imgcanny, Imgcanny, kernel); Scale edges values to 1 and invert values Imgcanny = imgcanny/255;
Imgcanny = 1-imgcanny;
Use float values to allow multiply between 0 and 1 Mat imgcannyf;
Imgcanny.convertto (IMGCANNYF, CV_32FC3);
Blur the edgest to do smooth effect smooth edge Blur (IMGCANNYF, IMGCANNYF, Size (5, 5));
/** color **///Apply bilateral filter to homogenizes color Mat imgbf;
Bilateralfilter (IMG, IMGBF, 9, 150.0, 150.0);
Truncate colors Mat result = IMGBF/25;
result = result * 25;
/** MERGES COLOR + EDGES **///Create a 3 channles for EDGES Mat;
Mat cannychannels[] = {IMGCANNYF, imgcannyf, IMGCANNYF};
Merge (Cannychannels, 3, imgcanny3c);
Convert color result to float Mat RESULTF;
Result.convertto (RESULTF, CV_32FC3);
Multiply color and edges matrices Multiply (RESULTF, imgcanny3c, RESULTF);
Convert to 8 bits color Resultf.convertto (result, CV_8UC3);
Show Image Imshow ("Cartoon Effect", result); }