How to slice/cut an image into pieces - c

So I have a function that receives OpenCV image and turns it into gray-scale.
void UseLSD(IplImage* destination)
{
IplImage *destinationForGS = cvCreateImage(cvSize(destination->width, destination->height),IPL_DEPTH_8U,1);
cvCvtColor(destination,destinationForGS,CV_RGB2GRAY);
}
How now to cut that image into images of size 10x10 pixels and iterate true them?
(width and height may not divide on 10 but if there would be some loss (like loss from 1*h to 9*h+9*h pixels per image) it would be OK for me. )
BTW can you output one of 10*10 images onto screen. please.

You can crop your images into small pieces like this (iteration not tested):
// source image
IplImage *source = cvLoadImage("lena.jpg", 1);
int roiSize = 10;
for(int j = 0; j < source->width/roiSize; ++j) {
for(int i = 0; i < source->height/roiSize; ++i) {
cvSetImageROI(source, cvRect(i*roiSize, j*roiSize, roiSize, roiSize));
// cropped image
IplImage *cropSource = cvCreateImage(cvGetSize(source), source->depth, source->nChannels);
// copy
cvCopy(source, cropSource, NULL);
// ... do what you want with your cropped image ...
// always reset the ROI
cvResetImageROI(source);
}
}

I think the simplest solution is to use Regions of Interest. Here is sample
/* load image */
IplImage *img1 = cvLoadImage("elvita.jpg", 1);
/* sets the Region of Interest
Note that the rectangle area has to be __INSIDE__ the image
You just iterate througt x and y.
*/
cvSetImageROI(img1, cvRect(x*10, y*10, x*10 + 10, y*10 + 10));
/* create destination image
Note that cvGetSize will return the width and the height of ROI */
IplImage *img2 = cvCreateImage(cvGetSize(img1),
img1->depth,
img1->nChannels);
/* copy subimage */
cvCopy(img1, img2, NULL);
/* always reset the Region of Interest */
cvResetImageROI(img1);

Related

How to use memset to add colours to a pixel array?

I have a program in C and SDL2 with a pixel array:
Uint32 *pixels = NULL;
pixels = (Uint32 *) malloc (sizeof(Uint32)*(Uint32)windowWidth*(Uint32)windowHeight);
memset(pixels, 255, (Uint32)windowWidth*(Uint32)windowHeight*sizeof(Uint32));
With memset, making my second parameter '255' sets all the pixels to white. Every other number below that sets the pixels to a shade of grey. How do I set these pixels to an actual colour?
I use this pixel array to set screen colour via the texture amongst other things. The texture has a pixel format of ARGB8888 so a four colour channel Hex value should work, no?
SDL_UpdateTexture(texture, NULL, pixels, (int)((Uint32)windowWidth * sizeof(Uint32)));
I have tried using hex such as 0xFFCC00FF but that just sets it to white.
The problem with memset is that it copies the same value to each byte. You want to use memcpy in a loop with a 4-byte value.
Uint32 numPixels = (Uint32)windowWidth * (Uint32)windowHeight;
Uint32 color = (Uint32)0xFFCC00FF;
for (Uint32 i = 0; i < numPixels; ++i)
{
memcpy(pixels + i * sizeof(Uint32), &color, sizeof(color));
}
Use a for loop:
Uint32 *pixels = NULL;
size_t nPixels = windowWidth * windowHeight;
pixels = malloc (sizeof (Uint32) * nPixels);
for (size_t c = 0; c < nPixels; c++) {
pixels[c] = color;
}
This doesn't use memset but thanks to #Banex I was able to come up with something that worked.
Uint32 colour = (Uint32)0xFFCC00FF;
int i,j;
for(i=0;i<windowWidth;i++)
{
for(j=0;j<windowHeight;j++)
{
pixels[i+j*windowWidth]=colour;
}
}

ImageMagick to write image file row by row (or band by band)

Does ImageMagick (C API MagickWand) have a functionality to generate an image file (.jpg, .tif) using RGB raster data?
If so, can it also generate an image file band by band, meaning write few rows at a time until it writes the whole image? Or one row at a time?
I believe you are describing image row iterators. ImageMagick provided PixelIterator methods to allow traversing of image data.
Here's a quick example.
#include <stdio.h>
#include <wand/MagickWand.h>
int main(int argc, const char * argv[]) {
// Set up IM environment.
MagickWandGenesis();
// Prototype
MagickWand * wand;
PixelWand * bg;
PixelIterator * iter;
PixelWand ** row;
MagickPixelPacket pixel;
size_t
x,
y,
row_width,
width = 200,
height = 50;
unsigned int
seed = 0xABCD;
// Allocate & initialize.
wand = NewMagickWand();
bg = NewPixelWand();
// Create an empty image.
PixelSetColor(bg, "WHITE");
MagickNewImage(wand, width, height, bg);
// Free color resource.
bg = DestroyPixelWand(bg);
srand(seed); // Seed random number.
// Allocate & initialize pixel iterator
iter = NewPixelIterator(wand);
// Loop through all rows.
for (y = 0; y < height; ++ y)
{
// Pull all pixels in a row.
row = PixelGetNextIteratorRow(iter, &row_width);
// Iterate over all pixels collected.
for (x = 0; x < row_width; ++x)
{
// Copy pixel data to packet.
PixelGetMagickColor(row[x], &pixel);
// Set random colors.
pixel.red = rand() & QuantumRange;
pixel.green = rand() & QuantumRange;
pixel.blue = rand() & QuantumRange;
// Put data back to pixel from packet.
PixelSetMagickColor(row[x], &pixel);
}
// Sync manipulated data on buffer back to image.
PixelSyncIterator(iter);
}
/******************************
Let's set row 16 to be all RED
******************************/
PixelSetIteratorRow(iter, 15);
row = PixelGetNextIteratorRow(iter, &row_width);
for (x = 0; x < row_width; ++x)
{
PixelGetMagickColor(row[x], &pixel);
pixel.red = QuantumRange;
pixel.green = 0;
pixel.blue = 0;
PixelSetMagickColor(row[x], &pixel);
}
// Sync manipulated data on buffer back to image.
PixelSyncIterator(iter);
// Free iterator resorce.
iter = DestroyPixelIterator(iter);
MagickWriteImage(wand, "/tmp/output.png");
// Free image data.
wand = DestroyMagickWand(wand);
MagickWandTerminus();
return 0;
}
Please note that the above example uses ImageMagick 6. For ImageMagick 7, please review Porting Guide.

c# WIA 12 bit grayscale image loses quality as bitmap

I am writing a windows forms application. I have an Image, received from CCD camera. The camera takes 12 bit grayscale tiff – 2 bytes per pixel. To receive it I am using WIA(windows image acquisition). I can make a byte array from the image data. After that I need to display the image in picturebox. When shown in picturebox, the image is too dark. Also, the created bitmap is Format32bppArgb. Do I lose quality, when creating the bitmap and how can I make the needed bitmap format? I am extremely new to image processing and any help will be great. I have read many forum posts on the topic of conversion between the formats, but with no luck so far.
So any ideas how to receive 16 bit grayscale bitmap from what I have so far?
Edit: This now is working:
private void btnAdvancedTestSnap_Click(object sender, EventArgs e)
{
WIA.CommonDialog _dialog = new CommonDialogClass();
WIA.Device _camera = _dialog.ShowSelectDevice(WIA.WiaDeviceType.CameraDeviceType, false, false);
ImageFile imageFile = (ImageFile)_camera.Items[1].Transfer(EnvFormatID.wiaFormatTIFF);
Byte[] receivedBytes = (byte[])imageFile.FileData.get_BinaryData();
int bytecount = receivedBytes.Length;
int width = imageFile.Width;
int height = imageFile.Height;
int dimension = width * height * 2;//number of bytes representing the image - 2 bytes per pixel
int startImgBytes = bytecount - dimension;
startImgBytes += 1;// from which position of the big array to start making pixel values
byte[] imageBytes = new byte[dimension]; //byte array with only bytes,representing the picture
int j = 0;
for (int i = startImgBytes; i < receivedBytes.Length; i++)//filling the only pixel byte data array
{
imageBytes[j] = receivedBytes[i];
j++;
}
int pixDimension = width * height; //number of pixels in the image
int[] pixVal = new int[pixDimension];
int z = 0;
for (int i = 0; i < imageBytes.Length; i+=2)
{
int res = (imageBytes[i] * 0x100) + imageBytes[i + 1];//int value of the pixel, 2 bytes per pixel
int pix = (res * 255) / 4095;// scalling down to 8 bit value
pixVal[z] = pix;
z++;
}
Bitmap newImage = new Bitmap(width, height, PixelFormat.Format24bppRgb);
Color p;
//grayscale
int counter = 0;
for (int y = 0; y < height; y++)//height
{
for (int x = 0; x < width; x++)//width
{
int val = pixVal[counter];
newImage.SetPixel(x,y,Color.FromArgb(255,val,val,val));
counter++;
}
}
pbAdvanced.Image = newImage; //show the image in picture box
But this method is very slow for high resolution. Any ideas how to improve the speed. I read examples with Marshal.Copy and lockbits, but in all examples they use a source image and copy to new. Any help will be greately appreciated

Syntax not clear about pointers and matrix

i am coding in C and i have to work with png images, so i work with libpng library. In my project i use this structure:
png_bytep *row_pointers; /* <-- to declare the pointer that will contain the image
and this to initialize the pointer to contain the image. */
row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
for(int y = 0; y < height; y++) {
row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png,info));
}
My problem is: after this piece of code my image is copyed in row_pointers and i want to copy it in a png_byte map[x][y] so i can work easly pixel for pixel.
Someone can help me?
Thanks
Ok. That is pointer to pointer!
png_bytep = pointer to png_byte
If you eliminate png_bytep and just use png_byte your code will look like this.
int height = 10;
int width = 20;
png_byte **row_pointers;
row_pointers = (png_byte**)malloc(sizeof(png_byte*) * height); <-- This is basically your number of rows.. ie height of your matrix.
for(int y = 0; y < height; y++)
{
row_pointers[y] = (png_byte*)malloc(sizeof(png_byte)*width); <-- This is representing number of elements in each row.. so width.
}
Assuming your structure have two ints x and y. you must be filing data as below..
for(int i=0;i< height;i++)
{
for (int j=0;j<width;j++)
{
row_pointers[i][j].x = i*j;
row_pointers[i][j].y = i*j;
}
}
Assuming your map also have similar structure. This is how you copy data..
for(int i=0;i< height;i++)
{
for (int j=0;j<width;j++)
{
map[i][j].x = row_pointers[i][j].x;
map[i][j].y = row_pointers[i][j].y;
}
}
Have a look at pnm2png.c in libpng's contrib/pngminus directory.
In this code, "png_pixels" is a simple array that holds all the pixels, and row_pointers is an array of pointers that point to the beginning of each row within png_pixels:
/* row_bytes is the width x number of channels x (bit-depth / 8) */
row_bytes = width * channels * ((bit_depth <= 8) ? 1 : 2);
png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))
/* set the individual row_pointers to point at the correct offsets */
for (i = 0; i < (height); i++)
row_pointers[i] = png_pixels + i * row_bytes;
/* now we can go ahead and just read the whole image */
png_read_image (png_ptr, row_pointers);
Once png_read_image completes, you can easily work with your pixels in the png_pixels array.
Notice that there is only one "malloc", which allocates png_pixels. Instead of doing a separate "malloc" for each row, this code calculates the values of the row_pointers.

Opencv corners detection for High resolution images

I've just implemented corner detection using OpenCV and i got the corner value as zero.i use 3488*2616 resolution camera images.it is there any proper way to find the corner detection for high resolution images.i d'not know where i did my mistake.Here with i've attached my code and images also.please help me.i'm very new to opencv.sorry for my English.
int board_w = 6;
int board_h = 6;
const int MAX_CORNERS = 500;
int main()
{
int board_n = (board_w-1) * (board_h-1);
CvSize board_sz = cvSize( board_w-1, board_h-1 );
CvPoint2D32f* corners = new CvPoint2D32f[board_n];
int cornerCount = 0;
IplImage *image = cvLoadImage("myimage.jpg");
IplImage *gray_image = cvCreateImage(cvGetSize(image),8,1);
cvCvtColor(image, gray_image, CV_BGR2GRAY );
const int N = cvFindChessboardCorners(gray_image,board_sz,&corners[0],&cornerCount,10);
cvFindCornerSubPix(gray_image,&corners[0],cornerCount,cvSize(3,3),cvSize(-1,-1),cvTermCriteria(CV_TERMCRIT_EPS,0,.01));
printf("\ the count was:%d \n",cornerCount);
for (int i = 0; i < cornerCount; i++)
{
cvCircle (image, cvPointFrom32f (corners[i]), 3, CV_RGB (0, 0, 255), 2);
}
cvNamedWindow("firstframe");
cvShowImage("firstframe",image);
cvWaitKey(0);
cvReleaseImage(&image);
cvReleaseImage(&gray_image);
}
The code will work for normal chessboard images.but while using real time camera images with that resolution it ll not works.please help me.thanks in advance.
If you suspect that detection is really failing simply because you are using high resolution images, you can always cvResize() your IplImage to a smaller size and verify your observation.

Resources