OpenCV 2.4 : C API for converting cvMat to IplImage - opencv

I'm having an YUYV image buffer in cvMat object (snippet shown below). I had to convert this cvMat object to IplImage for color conversion.
CvMat cvmat = cvMat(480, 640, CV_8UC2, yuyv_buff);
I tried the below options to convert this cvmat object to IplImage object (src: https://medium.com/#zixuan.wang/mat-cvmat-iplimage-2f9603b43909 ).
//cvGetImage()
CvMat M;
IplImage* img = cvCreateImageHeader(M.size(), M.depth(), M.channels());
cvGetImage(&M, img); //Deep Copy
//Or
CvMat M;
IplImage* img = cvGetImage(&M, cvCreateImageHeader(M.size(), M.depth(), M.channels()));
//cvConvert()
CvMat M;
IplImage* img = cvCreateImage(M.size(), M.depth(), M.channels());
cvConvert(&M, img); //Deep Copy
But nothing worked. cvGetImage(), cvConvert() expects cvArr* as input. Passing &cvmat to them throws exception.
Is there any other way to convert an CvMat object to IplImage object in OpenCV 2.4 ?
Note: I cannot use C++ API or any other version of OpenCV. I'm limited to use only OpenCV 2.4
Edit 1: My objective is to convert this YUYV buffer to an RGB image object.

Instead of creating cvMat, I was able to create an IplImage directly from the yuyv image buffer like below:
IplImage* frame = cvCreateImage(cvSize(640,480), IPL_DEPTH_8U, 2);
frame->imageData=(char*)yuyv_buffer;

Related

Image created does not display correctly

Hi I am using following function to create an image.
Mat im(584, 565, CV_8UC1, imgg);
imwrite("Output_Image.tif", im);
but the problem is that when I display the image "Output_Image.tif". Right hand side portion is overlapped onto the left handside portion. I am not able to understand what is happening. Please explain as I am beginner to opencv. Thanks
Are you sure that the image is CV_8UC1 (colospace grayscale)?
It looks like the image is an BGR image (Blue, Green, Red) and when you use an CV_8UC3 image as an CV_8UC1 image it does that.
Change this line:
Mat im(584, 565, CV_8UC1, imgg);
To this line:
Mat im(584, 565, CV_8UC3, imgg);
EDIT for mixChannels() (see comments):
C++: void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs)
the Mat* dst is an array of Mats which must be allocated with the right size and depth before calling mixChannels. In that array your cv::Mats will really have 1 channel.
Code Example:
cv::Mat rgb(500, 500, CV_8UC3, cv::Scalar(255,255,255));
cv::Mat redChannel(rgb.rows, rgb.cols, cv_8UC1);
cv::Mat greenChannel(rgb.rows, rgb.cols, cv_8UC1);
cv::Mat blueChannel(rgb.rows, rgb.cols, cv_8UC1);
cv::Mat outArray[] = {redChannel, greenChannel, blueChannel };
int from_to[] = {0,0 , 1,2 , 3,3};
cv::mixChannels(&rgb, 1, outArray, 3, from_to, 3);
Its a little bit more complex than the split() function so heres a link to the documentary, especially the from_to array is hard to understand at first
Link to documentation:
http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#mixchannels

how to obtain a single channel value image from HSV image in opencv 2.1?

I am a beginner in opencv. I am using opencv v2.1. I have converted an RGB image to HSV image. Now I want to obtain single channels Hue, Value and Saturation separately. What should I do? I have seen similar questions here but No-one answered that. Kindly help.
You can access the same way you were accessing for RGB image where 1st channel will be for H, 2nd channel for S and 3rd channel for V.
If you are using OpenCV 2.1, you must be using IplImage then, right?
like if your HSV image is
IplImage *src.
IplImage* h = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1 );
IplImage* s = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1 );
IplImage* v = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1 );
// Split image onto the color planes
cvSplit( src, h, s, v, NULL );
cvSplit function splits a multichannel array into several single channels. Correct me if I am wrong.
I would recommend using OpenCV 2.4. It has structs like cvMat which are very easy to handle just like 2D arrays.
EDIT:
If you are using Mat then you can separate the channels out easily.
Let's say your hsv mat is Mat img_hsv.
Then :
vector<Mat> hsv_planes;
split( img_hsv, hsv_planes );
hsv_planes[0] // H channel
hsv_planes[1] // S channel
hsv_planes[2] // V channel
See if you can work out with this.
Solution for Python:
import cv2
from matplotlib import pyplot as plt
# Read image in BGR
img_path = "test.jpg"
img = cv2.imread(img_path)
# Convert BGR to HSV and parse HSV
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = hsv_img[:, :, 0], hsv_img[:, :, 1], hsv_img[:, :, 2]
# Plot result images
plt.imshow("Original", cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.imshow("HSV", hsv_img)
plt.imshow("H", h)
plt.imshow("S", s)
plt.imshow("V", v)
plt.show()
Here it is for a Mat:
cv::Mat hsv_image = ...;
std::vector<cv::Mat> hsv_channels;
cv::split(hsv_image, hsv_channels);
cv::Mat h_image = hsv_channels[0];
cv::Mat s_image = hsv_channels[1];
cv::Mat v_image = hsv_channels[2];

how to write an opencv function that take one image as paramater and returns 2 images

i wanna build an opencv function that takes one IplImage image as parameter and returns 2 IplImage images. is this doable in opencv (c++). I prefer if it's using IplImage but i will appreciate other options
You can return several images by passing them by reference as function arguments. Example:
void myFunction(const cv::Mat& input_image, cv::Mat &output1, cv::Mat &output2) {
// modify output1
input_image.copyTo(output1);
rectangle(output1, cv::Rect(10,10,100,100), cv::Scalar(0,0,255), 2);
// modify output2
cvtColor(input_image,output2,CV_RGB2GRAY);
}
int main() {
cv::Mat input_image = imread("sample.jpg");
cv::Mat out1, out2;
myFunction(input_image, out1, out2);
// now out1 and out2 are modified by myFunction
}
Example is for cv::Mat but you can do the same with IplImage. You should use cv::Mat instead of IplImage.

Convert SDL_Surface to IplImage

I converted IplImage to SDL_Surface
With the reference of this link
SDL_Surface *single_channel_ipl_to_surface (IplImage *opencvimg)
{
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom((void*)opencvimg->imageData,
opencvimg->width,
opencvimg->height,
opencvimg->depth*opencvimg->nChannels,
opencvimg->widthStep,
1, 1, 1 ,0);
return surface;
}
How can I convert SDL_Surface to IplImage
There are 4 pieces of information you'll have to retrieve from SDL_Surface, so investigate the API to know how you can retrieve:
The size of the image (width/height);
The bit depth of the image;
The number of channels;
And the data (pixels) of the image;
After that you can create an IplImage from scratch with cvCreateImageHeader() followed by cvSetData().

Convert IPL_DEPTH_16S image in to IPL_DEPTH_8U in JavaCV

I have a One Image with depth of IPL_DEPTH_16S
IplImage result = cvCreateImage(cvGetSize(smoothImage), IPL_DEPTH_16S, 1);
cvSobel(smoothImage, result, 0, 1, 3);
and i want to pass that result image to other object which needs an IPL_DEPTH_8U image. So Is there any way to convert IPL_DEPTH_16S to IPL_DEPTH_8U in JavaCV.
I already try to use cvConvertScale() method. But i can't find what are the exact parametrs for that method.
Thankx..
Using the same style as your code, this should work:
IplImage i = cvCreateImage(cvGetSize(result), IPL_DEPTH_8U, 1);
cvConvertScale(result, i, 1, 0);

Resources