i am trying to do some image processing with Emgu CV.
I have raw pixel data of a gray image in an byte[]. I know the size of the image and the type.
I first create an image width the known size an type and then i want to load the date to the image (I have often done this in C++ OpenCV).
Image<Gray, Byte> image = new Image<Gray, byte>(width, height);
image.Bytes = data;
But the image is always kind of "cut through and puzzled together". It works with an image which width%4 = 0. That is why i assume it is some kind of "memory alignment" issue.
Has someone of you run into this problem and knows how to fix it?
Thanks,
Sebastian
Both your raw data and Image.Bytes are continuous pieces of memory. But every line of your array takes Width bytes, but line of Image takes Image.widthStep (I talk about IPLImage structure, don't know about Emgu pecularities) bytes, this value aligned for 4 bytes (99=>100 etc).
So you can or copy Width bytes for Yth line to Bytes[Y * widthStep] (height times), or create special 4-bytes-aligned array to collect raw data, then assign it to Image.Bytes
try using another constructor:
Image<Gray, Byte> image = new Image<Gray, byte>(width, height, bytesNum, data);
See also http://www.emgu.com/wiki/files/2.1.0.0/html/1d51c1ed-6f5e-65f9-206c-ef2d59c5c117.htm
Related
In C++ I am used to using stb_image to load image data to and from RAM.
I am writing a rust program where I have loaded some PNGs and JPEGs as raw binary data.
I am trying to use the image crate to read and decompress the ray byte data into the data and metadata (i.e. image dimensions and raw pixel byte data). I need to then re compress the data s a png and print it to disk, to make sure the data is ok (I will use the raw buffers later on).
To that effect I have this
let image_data = image::load_from_memory(bytes).unwrap();
where bytes is the raw image data.
Problem n1, this seems to create a 3 channel image for jpegs, I need a 4 channel image for both pngs and jpegs. So for jpegs I need the image crate to add padding. But if I try to cast it using as_rgba8 I can no longer get the width and the height of the image.
Then I am trying to read the data into a custom struct, like this:
let mut raw_data = Vec::<u8>::new();
let width = image_data.width() as usize;
let height = image_data.height() as usize;
raw_data.extend_from_slice(image_data.as_bytes());
println!("{}", image_data.width());
println!("{}", image_data.height());
println!("{}", image_data.height() * image_data.width() * 3);
println!("{}", raw_data.len());
let texture =
Texture
{
width,
height,
channel_num : 4,
format : ImageFormat::RGBA8,
data : raw_data,
};
This part seems to work, next I am trying to re-compress the data dn print to disk:
let tmp = RgbaImage::from_raw(
texture.width as u32,
texture.height as u32,
texture.data.as_bytes().to_vec()).unwrap();
tmp.save("tmp.png");
In this case I am getting a None error on attempting the unwrap. I don't understand why since the byte buffer does have enough data to contain the full image, it was literally created by that image.
I am somewhat lost.
[...] this seems to create a 3 channel image for jpegs, I need a 4 channel image for both pngs and jpegs. [...] But if I try to cast it using as_rgba8 I can no longer get the width and the height of the image.
You want to convert the underlying image buffer, rather than cast the image. This is done with the to_* family of methods in DynamicImage. This works regardless of whether the dynamic image was obtained from a file or from memory (both open and load_from_memory return a DynamicImage).
use image::{RgbaImage, open}; // 0.24.3
let img = open("example.jpg")?;
println!(
"Before: {}x{} {:?} ({} channels)",
img.width(),
img.height(),
img.color(),
img.color().channel_count()
);
let img: RgbaImage = img.to_rgba8();
println!(
"After: {}x{} ({} channels)",
img.width(),
img.height(),
img.sample_layout().channels
);
Note how the second img is already known at compile time to be an RGBA image. As an image buffer, you can freely retrieve any property or pixel data that you wish.
Possible output:
Before: 2864x2480 Rgb8 (3 channels)
After: 2864x2480 (4 channels)
I have an image with 26,4KB. It is loaded by the class Frame bellow. Why does the Profiling Tool from Flex shows a usage of 1388KB for this instance of Frame.
public class Frame extends Group
{
public function Frame(source:Object)// image with 26,4K
{
var image:BitmapImage;
image = new BitmapImage();
image.smooth = true;
image.source = source;
this.addElement(image);
}
}
BitmapImages are essentially an uncompressed rectangular array containing the bytes determining pixel colors.
I imagine your input file is a JPG/JPEG, PNG, GIF? (basically, it's compressed).
Imagine an image 100px by 100px, 32bit RGBA colors (Red/Green/Blue/Alpha).
The memory requirements for this BitmapImage would be in the neighborhood of 100 * 100 * (32 / 8) (X * Y * bytesPerPixel) = 40K bytes. But that SAME image as a JPG might compress down to 3K or something. (or GIF, or PNG, etc.)
It has to be stored as a bitmap at some point so that it can be copied (blitted) to video memory for display. Perhaps flex has alternative image storage types you could use/try?
I want to crop an image of 1176*640 to save the ROI of 1176*400 size. I am using the following snippet to acheive bit I am still getting the original image as output.
IplImage *CMyFunction::ROI(IplImage *pImage, CvRect ROI)
{
IplImage *mROI = cvCreateImage(cvGetSize(*pImage), IPL_DEPTH_8U, 1);
cvSetImageROI(pImage, rect_ROI);
cvCopy(pImage, mROI);
cvResetImageROI(pImage);
return mROI;
}
For cvCopy() the source and destination should be same size and type, that is the parameter like width, height, depth, and number of channel should be equal for both image. In your case you can change your code either like
IplImage *mROI = cvCreateImage(cvGetSize(pImage), pImage->depth, pImage->nChannels); //create dest with same size as source
cvSetImageROI(pImage, rect_ROI); //Set roi on source
cvSetImageROI(mROI, rect_ROI); //set roi on dest
cvCopy(pImage, mROI);
cvResetImageROI(pImage);
cvResetImageROI(mROI);
or
IplImage *mROI = cvCreateImage(cvSize(rect_ROI.width,rect_ROI.height), pImage->depth, pImage->nChannels); // create an image of size as rect
cvSetImageROI(pImage, rect_ROI); //set roi on source
cvCopy(pImage, mROI);
cvResetImageROI(pImage);
I understood that the pointer when leaves the function is no longer stable and declared a new IplImage* outside of the function and pass it as a parameter which proved to be efficient.
IplImage *CMyFunction::ROI(IplImage *pImage, CvRect ROI, IplImage* FinalImage)
I have a binary file of 16 bit Intensity of the image. I have read this data in short array. And create 16 bit gray Image using the following code.
IplImage *img=cvCreateImage( cvSize( Image_width, Image_height ), IPL_DEPTH_16S, 1 );
cvSetData(img,Data, sizeof(short )*Image_width);
Where Data is short array.
Then I set ROI for this Image using this function
cvSetImageROI(img, cvRect(crop_start.x, crop_start.y, crop_width, Image_height));
and ROI is being set successfully.
Now after setting the ROI I want to access the Intensity of the Image means I want pointer of the intensity of the cropped Image. I have tried this code to access the intensity
short *crop_Imagedata=(short *)img->imageData;
But This pointer is not giving the right Intensity as I have checked that by debugging the code.
Can any body please tell me how can I get pointer of the Image Intensity.
Thanks in Advance
Hello I have tryed the following to find what maybe you wannt to do:
IplImage *img=cvCreateImage( cvSize( 15, 15 ), IPL_DEPTH_16S, 1 );
cvSet(img,cvScalar(15));//sets all values to 15
cvSetImageROI(img, cvRect(4, 0, 10, 15));
short *crop_Imagedata=(short *)img->imageData;
((*crop_Imagedata) == 15) // true
The value that you will get is not in the roi! imageData of the IplImage structure is just a simple pointer and not a function !!! the rois of opencv is something that isn t that well documented and easy to use in my opinion. Maybe all algorithms of opencv use the rois somehow. I use them to but there is no such automatic function with the standard iplimage structure to simple use them.
If you wannt more magic try to use the new cv::Mat object...
but if you still wann t to use rois then you will have to allways to use
CvRect roi = cvGetImageROI(img);
method to check all the time the position. After that you will have to add the roi offset:
((short*)(img->imageData + (roi.y+ypos)*img-widthStep))[roi.x+xpos]
remember the standard Opencv is a C library not a C++ ! btw when mixing cv::Mat rois can be a bit annoying to. To copy an iplimage to a cv::Mat without roi I have to do the following:
CvRect roitmp = cvGetImageROI(ilimage);
cvResetImageROI(ilimage);
cv::Mat tmp = cv::Mat(ilimage).clone();
cvSetImageROI(ilimage,roitmp);
maybe here someone knows the right way of working with rois...
I have being study about OpenGL ES for iOS.
I wonder that data of YUV format is can display without converting RGB.
In most, the yuv data have to convert RGB for display. But, converting process is very slow, Then, that is not display smoothly.
So, I would like to try to dispaly YUV data without convert to RGB.
Is it possible? If possible, what can I do?
Please, let me give a advice.
I think it is not possible in OpenGL ES to display YUV data without convert to RGB data.
You can do this very easily using OpenGL ES 2.0 shaders. I use this technique for my super-fast iOS camera app SnappyCam. The fragment shader would perform the matrix multiplication to take you from YCbCr ("YUV") to RGB. You can have each {Y, Cb, Cr} channel in a separate GL_LUMINANCE texture, or combine the {Cb, Cr} textures together using a GL_LUMINANCE_ALPHA texture if your chrominance data is already interleaved (Apple call this a bi-planar format).
See my related answer to the question YUV to RGBA on Apple A4, should I use shaders or NEON? here on StackOverflow.
You may also do this using the fixed rendering pipeline of ES 1.1, but I haven't tried it. I would look toward the the texture blending functions, e.g. given in this OpenGL Texture Combiners Wiki Page.
Is you are looking solution for IOS, iPhone application then there are solution for that.
This is way convert CMSampleBufferRef to UIImage when video pixel type is set as kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
-(UIImage *) imageFromSamplePlanerPixelBuffer:(CMSampleBufferRef) sampleBuffer{
#autoreleasepool {
// Get a CMSampleBuffer's Core Video image buffer for the media data
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// Lock the base address of the pixel buffer
CVPixelBufferLockBaseAddress(imageBuffer, 0);
// Get the number of bytes per row for the plane pixel buffer
void *baseAddress = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
// Get the number of bytes per row for the plane pixel buffer
size_t bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer,0);
// Get the pixel buffer width and height
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
// Create a device-dependent gray color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
// Create a bitmap graphics context with the sample buffer data
CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8,
bytesPerRow, colorSpace, kCGImageAlphaNone);
// Create a Quartz image from the pixel data in the bitmap graphics context
CGImageRef quartzImage = CGBitmapContextCreateImage(context);
// Unlock the pixel buffer
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
// Free up the context and color space
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
// Create an image object from the Quartz image
UIImage *image = [UIImage imageWithCGImage:quartzImage];
// Release the Quartz image
CGImageRelease(quartzImage);
return (image);
}
}
If you are looking for Mobile devices then i can provide others to.