opencv how to create hsv format mat - c++

For example, I create
Mat mat1 = Mat::zeros(Size(100, 100), CV_8UC3);
and fill each pixel with (0, 255, 255), which is supposed to be red in hsv.
However, if I imshow this mat, this will be printed as a BGR image and is not red.
How do I make this mat hsv format and setting (0, 255, 255) result in red?

imshow assumes that the image you pass to it is in BGR color space. However, you can create a small function that does your imshow of HSV images.
void imshowHSV(std::string& name, cv::Mat& image)
{
cv::Mat hsv;
cv:cvtColor(image, hsv, CV_HSV2BGR);
cv::imshow(name, hsv);
}
But beware! this will convert and create a copy of the image, if you over use it it may have quite some overhead :)

Related

detect defects which are grayish in color from the image

I need to detect the defects which are more grayish in color.
I have tried removing noise from the image, thresholding the image but due to gray color of the defect, it becomes invisible or only the boundary remains. I don't know how to detect the defects , if I apply dilation it gets mixed with the surrounding circles.
Images with defects:
Images without defect:
My original image with the red pen marked defect is :
I have tried the below code:
//convert to grayscale
Mat gray_img;
cv::cvtColor(r_img, gray_img, COLOR_BGR2GRAY);
Mat dst1, dst2, dst;
cv::blur(gray_img, dst1, Size(3, 3));
cv::blur(gray_img, dst2, Size(7, 7));
cv::subtract(dst1, dst2, dst);
//thresholding
Mat thresh;
adaptiveThreshold(dst, thresh, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 5, 5);
Mat inv_thresh;
bitwise_not(thresh, inv_thresh);
My thresholded image is

Matrix multiplication between CV_8UC3 and CV_32FC3

I want to make matrix multiplication between image and mask. I want multiply in HSV value with 0.3. I think, the problem is between CV_32FC3 and CV_8UC3, but when I convert, still not work correct.
How can I do? Here is my current code:
Mat mask = Mat(frame.size(), CV_32FC3, cv::Scalar(1, 1, 1));
cv::fillConvexPoly(mask, pts, 3, cv::Scalar(1,1,0.3));
cvtColor(frame, frame, CV_BGR2HSV);
frame.convertTo(frame, CV_32FC3);
cv::multiply(frame,mask,frame);
frame.convertTo(frame, CV_8UC3);
cvtColor(frame, frame, CV_HSV2BGR);
If I do only this, see the mask is ok - white and black changes:
Mat mask = Mat(frame.size(), CV_32FC3, cv::Scalar(1, 1, 1));
cv::fillConvexPoly(mask, pts, 3, cv::Scalar(0,0,0));
imshow("mask", mask);

OpenCV: convert Scalar to different color space

I am using a Scalar to define the color of a rectangle I am drawing with OpenCV:
rectangle(imgOriginal, Point(0, 0), Point(25, 50), Scalar(H, S, V), CV_FILLED);
However, the color is defined in HSV color space rather than RGB (imgOriginal is RGB).
How do I convert Scalar (or its input, the integer variables H, S, and V) to RGB?
(So far I only found answers telling me how to convert a whole image with cvtColor which is not what I want.)
Although not optimal, You can use the following:
Scalar ScalarHSV2BGR(uchar H, uchar S, uchar V) {
Mat rgb;
Mat hsv(1,1, CV_8UC3, Scalar(H,S,V));
cvtColor(hsv, rgb, CV_HSV2BGR);
return Scalar(rgb.data[0], rgb.data[1], rgb.data[2]);
}
This worked for me,
Mat rgb;
Mat hsv(1, 1, CV_8UC3, Scalar(224, 224, 160));
cvtColor(hsv, rgb, CV_HSV2BGR);
Scalar rgb = Scalar((int)rgb.at<cv::Vec3b>(0, 0)[0],(int)rgb.at<cv::Vec3b>(0, 0)[0],(int)rgb.at<cv::Vec3b>(0, 0)[0])
OpenCV 3.2.0. Note: h is in range [0,360] and l and s is in [0,1]
Mat hls(1, 1, CV_32FC3, Scalar(h, l, s));
Mat rgb;
cvtColor(hls, rgb, COLOR_HLS2RGB);
Scalar c = Scalar(255*rgb.at<float>(0,0), 255*rgb.at<float>(0,1), 255*rgb.at<float>(0,2));
Use this to convert a single value:
cv::Vec3f rgb;
cv::Vec3f hsv;
hsv[0] = H;
hsv[1] = S;
hsv[2] = V;
cvtColor(hsv, rgb, CV_HSV2BGR);
Then you can use it:
rectangle(imgOriginal, Point(0, 0), Point(25, 50),
Scalar(rgb[0], rgb[1], rgb[2]), CV_FILLED);

Can't save image in JPG with white background OpenCV

I write a simple app in OpenCV that delete black background of an image and save it with white background in JPG. However, it's always saved with black background.
This is my code:
Mat Imgsrc = imread("../temp/temp1.jpg",1) ;
mat dest;
Mat temp, thr;
cvtColor(Imgsrc, temp, COLOR_BGR2GRAY);
threshold(temp,thr, 0, 255, THRESH_BINARY);
Mat rgb[3];
split(Imgsrc,rgb);
Mat rgba[4] = { rgb[0],rgb[1],rgb[2],thr };
merge(rgba,4,dest);
imwrite("../temp/r5.jpg", dest);
You can simply use setTo with a mask to set some pixels to a specific value according to a mask:
Mat src = imread("../temp/temp1.jpg",1) ;
Mat dst;
Mat gray, thr;
cvtColor(src, gray, COLOR_BGR2GRAY);
// Are you sure to use 0 as threshold value?
threshold(gray, thr, 0, 255, THRESH_BINARY);
// Clone src into dst
dst = src.clone();
// Set to white all pixels that are not zero in the mask
dst.setTo(Scalar(255,255,255) /*white*/, thr);
imwrite("../temp/r5.jpg", dst);
Also a few notes:
You can directly load an image as grayscale using: imread(..., IMREAD_GRAYSCALE);
You can avoid to use all those temporary Mats.
Are you sure you want to use 0 as threshold value? Because in this case you can avoid entirely to apply theshold, and set to white all pixels that are 0 in the grayscale image: dst.setTo(Scalar(255,255,255), gray == 0);
This is how I'd do:
// Load the image
Mat src = imread("path/to/img", IMREAD_COLOR);
// Convert to grayscale
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
// Set to white all pixels that are 0 in the grayscale image
src.setTo(Scalar(255,255,255), gray == 0)
// Save
imwrite("path/to/other/img", src);

How do I convert a cv::Mat to a cv::Rect

I have an Image in a cv::Mat as a face, I need the whole image in a cv::Rect object
I couldn't find how it is done
That or , if possible ,creating the Rect from an image in my directory
you don't convert a cv::Mat to a cv::Rect.
you want the part of the image inside that Rect ?
Mat roi = Mat(img,rect);
will give you the cropped region
cv::Mat can't directly give you a cv::Rect, but you can create your
own using the size() method of cv::Mat, and by assuming that the starting point of the cv::Rect is (0,0)
cv::Mat image;
// load your image into the cv::Mat
...
// now create the cv::Rect from the cv::Mat
cv::Rect rect = cv::Rect(0, 0, image.size().width, image.size().height);
Although, as #berak says, you can't convert a cv::Mat to a cv::Rect, I am guessing you want something like this (untested).
cv::Mat face; // you already have this with some data in it
cv::Mat image; // you already have this with some data in it
cv::Rect rect(x, y, w, h); // some place in image where you want face
// copy face into rectange within image
cv::resize(face, image(rect), cv::Size(rect.width, rect.height));