Matrix multiplication between CV_8UC3 and CV_32FC3 - c++

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);

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

Extract one colour channel from 4-dimensional cv::Mat

I'm working with OpenCV for a while and experiment with the DNN extension. My model has the input shape [1, 3, 224, 244] with pixel-depth uint8. So I put my m_inputImg which has 3-channels and 8 bit pixel depth in the function:
cv::dnn::blobFromImage(m_inputImg, m_inputImgTensor, 1.0, cv::Size(), cv::Scalar(), false, false, CV_8U);
Now I'm interested in having a Idea how my input image "lay" inside the cv::Mat tensor. Theoretically I know how the tensor looks like, but I don't understand how OpenCV do it. So to understand this I want to extract one colour channel. I've tried this:
cv::Mat blueImg = cv::Mat(cp->getModelConfigs().model[0].input.height,
cp->getModelConfigs().model[0].input.width,
CV_8UC3,
blob.ptr<uint8_t>(0, 0);
But what I get is something like that (see picture). I'm realy confused about that, can anybody help or has a good advice?
Thanks
cv::Size() will use the original image size. You are interpreting the data wrong. Here are 4 ways to interpret a 512x512 (cv::Size()) loaded blob-start from the lenna image:
input (512x512):
blob-start as a 512x512 single channel image:
blob-start as a 512x512 BGR image:
blob-start as a 224x224 BGR image:
blob-start as a 224x224 single channel:
here's the code:
int main()
{
cv::Mat img = cv::imread("C:/data/Lenna.png"); // 8UC3
cv::imshow("img", img);
cv::Mat blob;
cv::dnn::blobFromImage(img, blob, 1.0, cv::Size(), cv::Scalar(), false, false, CV_8U);
cv::Mat redImg = cv::Mat(img.rows,
img.cols,
CV_8UC1,
blob.ptr<uint8_t>(0, 0));
cv::imshow("blob 1", redImg);
cv::imwrite("red1.jpg", redImg);
cv::Mat redImg3C = cv::Mat(img.rows,
img.cols,
CV_8UC3,
blob.ptr<uint8_t>(0, 0));
cv::imshow("redImg3C", redImg3C);
cv::imwrite("red3C.jpg", redImg3C);
cv::Mat redImg224_3C = cv::Mat(224,
224,
CV_8UC3,
blob.ptr<uint8_t>(0, 0));
cv::imshow("redImg224_3C", redImg224_3C);
cv::imwrite("redImg224_3C.jpg", redImg224_3C);
cv::Mat redImg224_1C = cv::Mat(224,
224,
CV_8UC1,
blob.ptr<uint8_t>(0, 0));
cv::imshow("redImg224_1C", redImg224_1C);
cv::imwrite("redImg224_1C.jpg", redImg224_1C);
cv::waitKey(0);
}
Imho you have to do in your code:
cv::dnn::blobFromImage(m_inputImg, blob, 1.0, cv::Size(), cv::Scalar(), false, false, CV_8U);
cv::Mat blueImg = cv::Mat(m_inputImg.rows,
m_inputImg.cols,
CV_8UC3,
blob.ptr<uint8_t>(0, 0);
OR
cv::dnn::blobFromImage(m_inputImg, blob, 1.0, cv::Size(cp->getModelConfigs().model[0].input.width , cp->getModelConfigs().model[0].input.height), cv::Scalar(), false, false, CV_8U);
cv::Mat blueImg = cv::Mat(cp->getModelConfigs().model[0].input.height,
cp->getModelConfigs().model[0].input.width,
CV_8UC3,
blob.ptr<uint8_t>(0, 0);
In addition, here's the version of setting the spatial blob image size to a fixed size (e.g. the desired DNN input size):
cv::Mat blob2;
cv::dnn::blobFromImage(img, blob2, 1.0, cv::Size(224,224), cv::Scalar(), false, false, CV_8U);
cv::Mat blueImg224_1C = cv::Mat(224,
224,
CV_8UC1,
blob2.ptr<uint8_t>(0, 0));
cv::imshow("blueImg224_1C", blueImg224_1C);
cv::imwrite("blueImg224_1C.jpg", blueImg224_1C);
Giving this image:

opencv how to create hsv format mat

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 :)

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);