how to fill color into image, by considering small matrix size 3*3 or 6*6? in opencv - c++

How can i fill color to required image of type Mat,by considering the small matrix of 3*3,i searched the net,but couldn't find correct answer to implement,i hope u guys can help better,thanks in advance ,or else please upload some links if possible.

How can i fill color to required image of type Mat?
If you want to change the value of a Mat image, you can do as follows:
Grayscale (8UC1):
uchar intensity = img.at<uchar>(y, x) = value_you_want_to_fill;
Color image (BGR color ordering, the default format returned by imread):
img.at<Vec3b>(y, x) = Vec3b(B_value, G_value, R_value);

Related

How to increase the saturation values of an image using HSV (in OpenCV using C++)?

I was looking for a way to increase the saturation of some of my images using code and found the strategy of splitting a material with HSV and then increasing the S channel by a factor. However, I ran into some issues where the split channels were still in BGR (I think) because the output was just a greener tinted version of the original.
//Save original image to material
Mat orgImg = imread("sunset.jpg");
//Resize the image to be smaller
resize(orgImg, orgImg, Size(500, 500));
//Display the original image for comparison
imshow("Original Image", orgImg);
Mat g = Mat::zeros(Size(orgImg.cols, orgImg.rows), CV_8UC1);
Mat convertedHSV;
orgImg.convertTo(convertedHSV, COLOR_BGR2HSV);
Mat saturatedImg;
Mat HSVChannels[3];
split(convertedHSV, HSVChannels);
imshow("H", HSVChannels[0]);
imshow("S", HSVChannels[1]);
imshow("V", HSVChannels[2]);
HSVChannels[1] *= saturation;
merge(HSVChannels, 3, saturatedImg);
//Saturate the original image and save it to a new material.
//Display the new, saturated image.
imshow("Saturated", saturatedImg);
waitKey(0);
return 0;
This is my code and nothing I do makes it actually edit the saturation, all the outputs are just green tinted photos.
Note saturation is a public double that is usually set to around 1.5 or whatever you want.
Do not use cv::convertTo() here. It changes the bitdepth (and representation, int vs. float) of the image, not what you are trying to achieve, the color space.
Using it like that does not throw a warning or error though, because both type indicators (CV_8U, ...) and the colorspace indicators (COLOR_BGR2HSV,...) can be resolved as integers, one is a #define, the other a old style enum.
Following the example here, it is possible to do with cv::cvtColor(). Don't forget to revert back before showing the image, imshow() and imwrite() both expect an BGR format.
// Convert image from BGR -> HSV:
// orgImg.convertTo(convertedHSV, COLOR_BGR2HSV); // <- this wrong, do not use
cvtColor(orgImg, convertedHSV, COLOR_BGR2HSV); // <- this does the trick instead
// to the split, multiplication, merge
// [...]
// Convert image back HSV -> BGR:
cvtColor(saturatedImg, saturatedImg, COLOR_HSV2BGR);
//Display the new, saturated image.
imshow("Saturated", saturatedImg);
Note that oCV does not care about color representation when working with a 3 channel Mat: Could be RGB, HSV or anything else. Only for displaying (or saving to an image format) does the given color space matter.

C++ How to make transparent watermark using OpenCV?

I am trying to make my watermark transparent with low opacity, but it seems just setting the colors to white:
This is the code I'm using which BTW I found in some website
/////////////////// Blending Images (Making Alpha) ////////////////////////
int main()
{
Mat img, img_bgra;
string img_path = "res/test.png";
img = imread(img_path);
if (img.data == NULL)
{
cout << "Image is not loaded!" << endl;
return -1;
}
cvtColor(img, img_bgra, ColorConversionCodes::COLOR_BGR2BGRA);
vector<Mat> channels(4);
split(img_bgra, channels);
channels[3] = channels[3] * 0.1;
merge(channels.data(), 4, img_bgra);
imwrite("res/transparent.png", img_bgra);
imshow("Image", img_bgra);
waitKey(0);
return 0;
}
I want the watermark to be displayed like this:
How can I achieve that?
i`m no good with C++, so i will try to explain with python example, hopefully this will be readable enough to help
alpha = 0.1 # maximum watermark opacity
imageSource = cv2.imread("res/test.png") # assuming BGR, uint8
imageWatermark = cv2.imread("res/transparent.png") # assuming BGRA, uint8
maskWatermark = imageWatermark[:,:, 3] # copy the alpha(transparency) channel, uint8
maskWatermark = np.float32(maskWatermark)*(1/255)*alpha # convert to float, normalize, apply transparency mul
maskSource = 1 -maskWatermark # float32, mask out the things we want to keep
imageWatermark = cv2.cvtColor(imageWatermark, cv2.COLOR_BGRA2BGR) # convert to same colorspace as source (3 channels), uint8
imageResult = np.uint8( np.float32(imageSource)*maskSource
+np.float32(imageWatermark)*maskWatermark)) # blend, convert to uint8
cv2.imshow('result', imageResult)
Key points here are:
some sort of mask is needed to tell which pixels of watermark are
going to affect the resulting image
blending is like interpolation between two color vectors, where
opacity acts like t-coordinate; this is done for each correspoinding
pixel pairs of two images
carefully watch data types to avoid overflow
images must be of same dimensions; if they`re not, you should shrink
or extend them in some way. I think that watermark is most likely is
much smaller than the image is. In this case you may want to copy the
watermarke part of the image (which matches watermark dimensions),
apply watermark and then copy back the watermarked fragment

Image Processing How to Apply gradient [-1 | 0 | 1 ] to RGB image

I need to apply gradient operator to RGB bitmap image. It works for 8 bit image but having the difficulty in implementing same for 24 bit image. Here is my code. Can anyone see how
to correct the zorizontal gradient operation to RGB image.
if (iBitPerPixel == 24) ////RGB 24 bits image
{
for(int i=0; i<iHeight; i++)
for(int j=1; j<iWidth-4; j++)
{
//pImg_Gradient[i*Wp+j] = pImg[i*Wp+j+1] - pImg[i*Wp+j-1] ;
int level = pImg[i*Wp+j*3+1] - pImg[i*Wp+j*3-1] ;
pImg_Gradient[i*Wp+j*3] = level;
// pImg_Gradient[i*Wp+j*3] = level;
// pImg_Gradient[i*Wp+j*3+1] = level;
// pImg_Gradient[i*Wp+j*3+2]= level;
}
for(int i=0; i<iHeight; i++)
for(int j=0; j<iWidth; j++)
{
// Copy the convetred values to original image.
pImg[i*Wp+j] = (BYTE) pImg_Gradient[i*Wp+j];
}
//delete pImg_Gradient;
}
Unfortunately, it is not clear how to define a gradient of an RGB image. The best way to go is to transform the image into a color space that separates intensity from color, such as HSV, and compute the gradient of the intensity component. Alternatively, you can compute the gradient of each color channel separately, and then combine the results in some way, such as taking the average.
Also see Edge detectors for RGB images?
In order to calculate the Gradient of an image (Which is a vector) you need to calculate both the horizontal and vertical derivative of the image.
Since we're dealing with a discrete image we should use Finitie Difference approximations of the derivative.
There are many ways to approximate, many of them are listed on the Wikipedia Pages:
http://en.wikipedia.org/wiki/Finite_difference
http://en.wikipedia.org/wiki/Finite_difference_method
http://en.wikipedia.org/wiki/Finite_difference_coefficients
Basically those are Spatial Coefficients hence you can define a filter using them and just filter the image.
This would be the most efficient way to calculate the gradient.
So, all you need is to find a library (Such as Open CV) which supports filtering images and you're done.
For color images, usually, you just calculate the Gradient per Color Channel.
Good Luck.
From your code; you are trying to calculate gradient from RGB but there is nothing to indicate how RGB is stored in your image. A complete guess is that in your image you have BGRBGRBGR...etc.
In that case your code is getting the gradient from the green channel, then storing it in the red of the gradient image. You don't show the gradient image being cleared to 0 - if you don't do this then it will probably be full of junk.
My suggestion is to convert to a greyscale image first; then you can use your original code.
Or calculate a gradient for each colour channel.

getting Y value[Ycbcr] of one Pixel in opencv

I'm trying to get the Y value of pixel from a frame that's in Ycbcr color mode.
here what I' wrote:
cv::Mat frame, Ycbcrframe, helpframe;
........
cvtColor(frame,yCbCrFrame,CV_RGB2YCrCb); // converting to Ycbcr
Vec3b intensity =yCbCrFrame.at<uchar>(YPoint);
uchar yv = intensity.val[0]; // I thought it's my Y value but its not, coz he gives me I think the Blue channel of RGB color space
any Idea how what the correct way to do that
what about the following code?
Vec3f Y_pix = YCbCrframe.at<Vec3f>(rows, cols);
int pixelval = Y_pix[0];
(P.S. I havent tried it yet)
You need to know both the depth (numerical format and precision of channel sample) as well as the channel count (typically 3, but can also be 1 (monochrome) or 4 (alpha-containing)), ahead of time.
For 3-channel, 8-bit unsigned integer (a.k.a. byte or uchar) pixel format, each pixel can be accessed with
mat8UC3.at<cv::Vec3b>(pt);

OpenCV: Shift/Align face image relative to reference Image (Image Registration)

I am new to OpenCV2 and working on a project in emotion recognition and would like to align a facial image in relation to a reference facial image. I would like to get the image translation working before moving to rotation. Current idea is to run a search within a limited range on both x and y coordinates and use the sum of squared differences as error metric to select the optimal x/y parameters to align the image. I'm using the OpenCV face_cascade function to detect the face images, all images are resized to a fixed (128x128). Question: Which parameters of the Mat image do I need to modify to shift the image in a positive/negative direction on both x and y axis? I believe setImageROI is no longer supported by Mat datatypes? I have the ROIs for both faces available however I am unsure how to use them.
void alignImage(vector<Rect> faceROIstore, vector<Mat> faceIMGstore)
{
Mat refimg = faceIMGstore[1]; //reference image
Mat dispimg = faceIMGstore[52]; // "displaced" version of reference image
//Rect refROI = faceROIstore[1]; //Bounding box for face in reference image
//Rect dispROI = faceROIstore[52]; //Bounding box for face in displaced image
Mat aligned;
matchTemplate(dispimg, refimg, aligned, CV_TM_SQDIFF_NORMED);
imshow("Aligned image", aligned);
}
The idea for this approach is based on Image Alignment Tutorial by Richard Szeliski Working on Windows with OpenCV 2.4. Any suggestions are much appreciated.
cv::Mat does support ROI. (But it does not support COI - channel-of-interest.)
To apply ROI you can use operator() or special constructor:
Mat refimgROI = faceIMGstore[1](faceROIstore[1]); //reference image ROI
Mat dispimgROI(faceIMGstore[52], faceROIstore[52]); // "displaced" version of reference image ROI
And to find the best position inside a displaced image you can utilize matchTemplate function.
Based on your comments I can suggest the following code which will find the best position of reference patch nearby the second (displaced) patch:
Mat ref = faceIMGstore[1](faceROIstore[1]);
Mat disp = faceIMGstore[52](faceROIstore[52]);
disp = disp.adjustROI(5,5,5,5); //allow 5 pixel max adjustment in any direction
if(disp.cols < ref.cols || disp.rows < ref.rows)
return 0;
Mat map;
cv::matchTemplate( disp, ref, map, CV_TM_SQDIFF_NORMED );
Point minLoc;
cv::minMaxLoc( map, 0, &minLoc );
Mat adjusted = disp(Rect(minLoc.x, minLoc.y, ref.cols, ref.rows));