How to create image from IplImage struct? - c++

I am not very familiar with old opencv codes. I have an IplImage struct:
IplImage *X;
This struct filled up with data that program reads from a device. I want to show it as image in my gui program. But I am not sure which properties I need to use.
EDIT:
Values of IplImage structs all properties with same order in docs(https://docs.opencv.org/3.4/d6/d5b/structIplImage.html):
4
0
0x557684eba3b4
0x557684eba3a4
GRAY
GRAYGRAY
0
16
192
0
�J�ಃ�O�ӳD������I���|�㲏�u������³��t�p�ݲ?�����F�Q�ⲿ���)���ҳ3�7�|�Ӳ������`�����_�I�_�Ͳ���{����E�5�p���(�(�D�|���L�L�W�����Q�,�r�D�L���ز��³�������������ҳ�̲�0������ܳ��,�³dzj�׳��$�|�����u����N���$���Q�ȳ��ܳڳ��������
�J�ಃ�O�ӳD������I���|�㲏�u������³��t�p�ݲ?�����F�Q�ⲿ���)���ҳ3�7�|�Ӳ������`�����_�I�_�Ͳ���{����E�5�p���(�(�D�|���L�L�W�����Q�,�r�D�L���ز��³�������������ҳ�̲�0������ܳ��,�³dzj�׳��$�|�����u����N���$���Q�ȳ��ܳڳ��������
0
49152
0
1
144
0
0
0
127
256

Related

How do I write encoded information (JPEG/JFIF) when it is not a multiple of eight?

I'm trying to write a baseline JPEG encoder. I already know how the handle the JFIF format (very good article, BTW). Right now I'm trying to compress a 8x8 grayscale image that is basically white. So, considering that a white pixel is basically 255, once you apply the JPEG algorithm (obviating the zig zag step, because for this example it is basically unnecessary) you get this matrix:
B = [63 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0]
As we can see, there's only one DC component (63) and no AC components. If you check the Huffman tables you find that the category is 6 (1110) and because 63 in binary is 111111 the sequence of bits for this DC component is 1110111111 (10 bits). Now, according to the algorithm, when all AC components are 0 you need to send EOB, whose sequence is 1010 (four bits). So, in the end, the final sequence of bits is 11101111111010 (14 bits).
Now, we already know that I can only write (or append) bytes to a file. So I am trying to write something like this to a new .jpeg file:
0xFF 0xD8 .. JFIF metadata ... 11101111111010 0xFF 0xD9
SOI marker block EOI marker
The question is, what should I do about those 14 bits? I guess I need to insert 2 filler bits (I don't know if there's a better term for them) to get 2 bytes but I don't know where to insert them, let alone their values (00? 01? 10? 11?). I suppose that this is a common problem in data encoding and/or low-level programming so I it is widely solved :)
The JPEG format says that:
The only padding that occurs is at the end of the scan when the remaining bits in the last byte to be filled with 1’s if the byte is incomplete.
So you are supposed to fill with 1-s here. That means in fine you should have:
1110 111111 1010 11
DC code DC value (=63) EOB (=10) Extra 1-s
In other words 11101111 11101011 which gives the 0xEF 0xEB sequence in hexadecimal.
Pro-tip: you can refer to this code section from jpec - a tiny JPEG encoder written in C. Also, the jpec_huff_write_bits includes a relevant documentation that may help you understand how to write the bits at Huffman time.

OpenCV imencode pgm doesn't encode the correct format

I am trying to encode a Mat CV_32FC1 image to send it over the internet with base64, the process works but the OpenCV encodes in the wrong format. Example:
vector<unsigned char> buffer;
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_PXM_BINARY);
compression_params.push_back(0);
cv::imencode(".pgm", desc, buffer, compression_params);
printf("%s", &buffer[0]);
This generates the following output:
P2
64 15
255
0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
etc..
According to the compression parameter and the first parameter (P2) it shouldn't be encoded as a binary format, it should be ASCII. (Source)
In itself this isn't a problem, but when I change compression_params.push_back(0) to compression_params.push_back(1) I get this output (without image data):
P5
64 15
255
I am using OpenCV 2.4.4 on iOS, how can I fix this or alternatively how can I send a Mat the good way without losing data?
Don't know if you have resolved your problem but I figured out the problem and it might apply to your case too even though you are using the iOS version, which I am not familiar with:
How do I capture images in OpenCV and saving in pgm format?

OpenCV - get grey value from an image

Hello everybody right now I'm trying to getting grey value for every pixel in an image
what I mean with grey value is the white or black level from an image let's say 0 for white and 1 for black. for an example for this image
the value I want will be like
0 0 0 0 0 0
0 1 1 1 0 0
0 0 1 1 0 0
0 0 1 1 0 0
0 0 1 1 0 0
0 0 1 1 0 0
0 0 1 1 0 0
0 0 0 0 0 0
is this possible? if yes how to do it with OpenCV in C? or if it's impossible with OpenCV is there any other library that can do this?
What you ask is certainly possible but how it can be done depends on a lot of things. If you use C++, on SO we generally expect you to use the C++ interface which means you have a cv::Mat object and loaded the image with something like this: (using namespace cv)
#include <opencv2/core/core.hpp>
Mat mat_gray = imread(path, CV_LOAD_IMAGE_GRAYSCALE);
or by
Mat mat = imread(path); // and assuming it was originally a color image...
Mat mat_gray;
cvtColor(mat, mat_gray, CV_BGR2GRAY); //...convert it to grayscale.
Now, if you just want to access pixel values one-by-one, you use _Tp& mat.at<_Tp>(int x,int y);. That is:
for(int x=0; x<mat_gray.rows; ++x)
for(int y=0; y<mat_gray.cols; ++y)
mat_gray.at<uchar>(x,y); // if mat.type == CV_8U
You can look up your type here, which you should use in place of uchar if the mat.type is other than CV_8U.
As for the pure C interface, you can check this answer. But if you use C++, you should definitely use the C++ interface.

Sending a control signal?

I am working on making a client and a server with windows, c++
the design what I decided is
server is just sending what client have to render depends on client's sending message.
sort of tiles and objects, picture, line, rectangle, circle... could be drawn on client side
and a client just receive a command from server and render something
if server send a message like "draw picture.png srcX srcY width height destX destY".
(picture.png is there on client side)
then client just parse string and do what I want to.
but.
I want to send a control signal as well
as like below
"for(y = 0; y<30; y++){ for(x = 0; x<30; x++) { draw tile.png 0 0 16 16 x*16 y*16 }}"
I realize that sending a function is not a good idea
(thanks for all replies.)
is there any good idea to solve this problem?
sending
"draw tile.png 0 0 16 16 0 0"
"draw tile.png 0 0 16 16 0 16"
"draw tile.png 0 0 16 16 0 32"
"draw tile.png 0 0 16 16 0 48"
"draw tile.png 0 0 16 16 0 64"
"draw tile.png 0 0 16 16 0 96"
"draw tile.png 0 0 16 16 0 112"
"draw tile.png 0 0 16 16 0 128"
"draw tile.png 0 0 16 16 0 132"
...for 30*30 time would be overkill
I am searching for efficient way for sending a message "what client have to draw"
drawing is not limited to just tile and object but it may contain drawing effect picture command on any coordinates.
thanks for reading.
Well, if you don't want to send and execute scripts, try to find some simple solution. For example, message format can be defined as:
draw file name srcX srcY width height destX destY [srcX srcY width height destX destY ...]
Some optimization may be applied, for example, you can pass only the difference between previous and current image:
draw tile.png 0 0 16 16 0 0 (5 16)
That means: increase member #5 of previous packet by 16.
I know this is quite primitive, but simple for implementation.
Define a language, implement the parser on the client and send the commands as pure text.
You'll have to implement the reverse parser in the server to send optimized messages too.

OpenCV read image and manage their pixel with integer values (like matlab)

In matlab when I use imread function the pixel values of an image are stored in a 3D matrix (of uint8). The values of the matrix are between 0 and 255. But in OpenCV the imread function stores the values in a cv::Mat. When I try to see the values of the pixels I see float values and when I try to convert to integer I have big values.
How can I see the cv::Mat components (RGB) with values between 0 and 255 like in Matlab?
Thanks in advance!
cv::Mat can be used with any type of pixel, if you use imread it will create a cv::Mat of the correct type.
Floating point images are unusual - are you sure the source data is floating point or are you just printing the values wrong?
You can convert a floating point image into 8bit ( CV8UC3) with cvtcolor()
int red = (int)((uchar*)pImg->imageData)[y*((int)pImg->widthStep)+x*3+C];
Those are for IplImage. Don't know if works for Mat. C=(0 or 1 or 2) is for color channel.
An example of the results
i have this:
Canny(test,edges,0.9*av[0],2*av[0],3,true);
for(int i=0;i<edges.rows;i++){
for(int j=0;j<edges.cols;j++){
cv::Vec2w& elem = edges.at<cv::Vec2w>(i,j);
std::cout << elem[0] << " , "<<elem[1] << std::endl;
}
}
the edges (cv::Mat) variable storage the result of cv::Canny function (a binary image) .. when i try to see the values of pixels using cv::Vec2w i have this for result:
6408 , 2058
1817 , 7433
1540 , 282
5386 , 1024
15 , 4867
768 , 275
1285 , 512
2 , 0
0 , 0
1 , 256
with cv::Vec2
0 , 0
0 , 0
0 , 0
0 , 0
0 , -256
255 , -256
0 , 0
0 , 0
with cv::Vec2i
0 , 0
0 , 0
-16777216 , -16776961
0 , 0
0 , -256
-1 , 65535
0 , -16777216
65535 , 0
0 , 0
and so on...
But for example if i write this image (imwrite("image.pgm",edges) ) and then reading with armadillo (the image es a single channel binary image) i have for the result an matrix (nx1) with values between 0 and 255 .. i know .. the format of both libraries is different, but .. i supose: binary image always have values 0 and 255 in one channel ....
I normally store images in type IplImage* rather than cv::Mat. If I say IplImage* frame = (get image somehow...), then I can say frame->imageData to see the values you are interested in. The values are arranged for an RGB image in a single array [r1, b1, g1, r2, b2, g2, r3, b3, g3, ..., r(height*width), b(height*width), g(height*width)], and I believe they are arranged row-wise.
What you need is edges.at<cv::Vec2b>(i,j), not cv::Vec2w or cv::Vec2i.