What is the size of ppvBits returned by CreateDIBSection? - winapi

I am trying to capture the screen. I call CreateDIBSection using a BITMAPINFO initialized with the screen dimensions, number of planes = 1, bpp = 32, mode = rgb. It then returns me a pointer to the bitmap data in ppvBits. But how do I determine how many bytes are in this buffer? It doesn't fill out the biSizeImage for me. Should I be computing it from the bpp and dimensions? Something like width * height * (bpp/8)?

The docs for BITMAPINFOHEADER explain how to calculate the "stride" - that is the number of bytes from one row to the next.
For uncompressed RGB formats, the minimum stride is always the image
width in bytes, rounded up to the nearest DWORD. You can use the
following formula to calculate the stride:
stride = ((((biWidth * biBitCount) + 31) & ~31) >> 3)
To calculate the total number of bytes required for a bitmap you multiply the stride by the number of rows.
Note the requirement for bitmap rows to be DWORD-aligned - this is why the stride calculation is rounded up.

Related

Image Classification - What is pixel depth?

I am following the Deep Learning course on Udacity. I am slightly confused about pixel depth and how it is being used in below code:
image_size = 28 # Pixel width and height.
pixel_depth = 255.0 # Number of levels per pixel.
image_data = (ndimage.imread(image_file).astype(float) -
pixel_depth / 2) / pixel_depth
Can someone explain me why we are doing pixel_depth / 2) / pixel_depth while reading the image into N-d array?
Depth in CV just refers to the data type. Depth of 255.0 implies 8-bits for each pixel and so on.
pixel_depth / 2) / pixel_depth
This bit of code seems a little weird at first but it's purpose is to normalize the image to a range of -0.5 to 0.5, which is a common tactic to simplify image processing.
Pixel depth is the number of values that a pixel can take. For 8-bits images, this is 256 (but they use 255 here).
The code here is used to normalize and center the pixel values into the interval [-0.5,0.5].

resizing image with rmagick/imagemagick to be less than a specified product of its width and height

I'm running a script that resizes images that are too large. I've used "resize_to_fit" to reduce images to a specific pixel size depending on the longer side, but I'm wondering if it's possible to do it with this logic instead: for any image whose width x height product is greater than a set value, resize the image so that the new width and height values are as large as possible while still being under that value. In other words, I don't want to arbitrarily resize the dimensions more than necessary, and I'd want to retain aspect ratio in this conversion. This may be more of a math question than a ruby one, but in any case, this is what I've tried:
image = Magick::Image.read(image_file)[0];
dimensions = image.columns, image.rows
resolution = dimensions[0] * dimensions[1]
if resolution > 4000000
resolution_ratio = 4000000 / resolution.to_f
dimension_ratio = dimensions[0].to_f * resolution_ratio
img = img.resize_to_fit(dimension_ratio,dimension_ratio)
img.write("#{image}")
end
So let's say an image has a width of 2793px and a height of 1970px. The resolution would be 5,502,210. It thus goes through the conditional statement, and as of right now, outputs a new width of 2030 and height of 1432. The product of these two is 2,906,960—which is obviously well under 4,000,000. But there are other possible width x height combinations whose product could be much closer to 4,000,000 pixels than 2,906,960 is. Is there a way of determining that information, and then resizing it accordingly?
You need to properly calculate the ratio, which is a square root from your desired dimension divided by (row multiplied by col):
row, col = [2793, 1970]
ratio = Math.sqrt(4_000_000.0 / (row * col))
[row, col].map &ratio.method(:*)
#⇒ [
# [0] 2381.400006266842,
# [1] 1679.6842149465374
#]
[row, col].map(&ratio.method(:*)).reduce(:*)
#∞ 3999999.9999999995

Matlab: crop image with a sliding window?

does anybody know how to crop an image with a sliding window in Matlab?
e.g. I have an image of 1000x500 pixels, I would like to crop from this image blocks of 50x50 pixels... Of course I have to handle uneven divisions, but it is not necessary to have block of the same size.
Some details that have helped me in the past related to (i) ways to divide an image while block processing and (ii) "uneven division", as mentioned by OP.
(i) Ways to divide/process an image:
1. Process non-overlapping blocks:
Using default parameter {'BorderSize',[0 0]}, this can be handled with blockproc as below.
Example for (i)-1: Note the blocked nature of the output. Here each non-overlapping block of size 32 x 32 is used to calculate the std2() and the output std2 value is used to fill that particular block. The input and output are of size 32 x 32.
fun = #(block_struct) std2(block_struct.data) * ones(size(block_struct.data));
I2 = blockproc('moon.tif',[32 32],fun);
figure; subplot(1, 2, 1);
imshow('moon.tif'); title('input');
subplot(1,2, 2)
imshow(I2,[]); title('output');
Input and Output Image:
(i)-2: Process overlapping blocks:
Using parameter {'BorderSize',[V H]}: V rows are added above and below the block and H columns are added to the left and right of the block. The block that is processed has (N + 2*V) rows and (M + 2*H) columns. Using default parameter {'TrimBorder',true}, the border of the output is trimmed to the original input block size of N rows and M columns.
Example for (i)-2: Below code using blockproc uses {'BorderSize',[15 15]} with [N M] = [1 1]. This is similar to filtering each pixel of the image with a custom kernel. So the input to the processing unit is a block of size (1 + 2*15) rows and (1 + 2*15) columns. And since {'TrimBorder',true} by default, the std2 of the 31 rows by 31 columns block is provided as output for each pixel. The output is of size 1 by 1 after trimming border. Consequently, note that this example output is 'non-blocked' in contrast to the previous example. This code takes much longer time to process all the pixels.
fun = #(block_struct) std2(block_struct.data) * ones(size(block_struct.data));
I2 = blockproc('moon.tif',[1 1],fun,'BorderSize',[15 15]);
figure; subplot(1, 2, 1);
imshow('moon.tif'); title('input');
subplot(1,2, 2)
imshow(I2,[]); title('output');
Input and Output Image:
(ii) "Uneven division":
1. Zero/replicate/symmetric padding:
Zero padding so that an integer multiple of the blocks (N rows by M cols sized) can cover the [image + bounding zeros] in the uneven dimension. This can be achieved by using the default parameter {'PadMethod', 0} along with {'PadPartialBlocks' , true} ( which is false by default ). If a bounding region of zeros causes a high discontinuity in values computed from the bounding blocks, {'PadMethod', 'replicate'} or {'PadMethod', 'symmetric'} can be used.
2. Assume an "Active Region" within the image for block processing
For the case of processing each pixel, as in case (i)-2, we could assuming a bounding region of floor(block_size/2) pixels on all sides along the periphery of the image that is used as "Dummy" region. The Active region for block processing is contained within the Dummy region.
Something similar is used in imaging sensors where Dummy Pixels located at the periphery of an imaging array of Active Pixels allow for an operation like the color interpolation of all active area pixels. As color interpolation usually needs a 5x5 pixel mask to interpolate the color values of a pixel a bounding Dummy periphery of 2 pixels can be used.
Assuming MATLAB indexing, the region ( floor(block_size/2) + 1 ) to ( Input_Image_Rows - floor(block_size)/2) ) Rows by ( floor(block_size/2) + 1 ) to ( Input_ImageCols - floor(block_size)/2) ) Columns is considered as Active region (assuming a square block of side, block_size) which undergoes block processing for each pixel as in (i)-2.
Assuming a square block size of 5 by 5, this is shown by the following:
block_size = 5;
buffer_size = floor(block_size/2);
for i = (buffer_size+1):(image_rows-buffer_size)
for j = (buffer_size+1):(image_cols-buffer_size)
... % block processing for each pixel Image(i,j)
end
end
Matlab ver: R2013a
I would first look into the function blockproc to see if it can do what you want.
If you're sure you want to manually crop the image into blocks, you can use this script. It both writes the cropped images to .png files and saves the cropped images in the pages of a 3D array. You can modify it as you need.
This script assumes the image in evenly divisible by the block size. If it isn't, you'll need to pad it with zeros.
[rowstmp,colstmp]= size(myImage);
block_height = 50;
block_width = 50;
blocks_per_row = rows/block_height;
blocks_per_col = cols/block_width;
number_of_blocks = blocks_per_row*blocks_per_col;
%// pad image with zeros if needed
if ~(mod(rowstmp-1,block_height)==0)
rows = ceil(rowstmp/block_height)*block_height;
end
if ~(mod(colstmp-1,block_width)==0)
cols = ceil(colstmp/block_width)*block_width;
end
Im = uint8(zeros(rows,cols));
Im(1:rowstmp,1:colstmp) = myImage;
%// make sure these image have type uint8 so they save properly
cropped_image = uint8(zeros(rows,cols));
img_stack = uint8(zeros(rows,cols,number_of_blocks));
%// loop over the image blocks
for i = 1:blocks_per_row
for j = 1:blocks_per_col
%// get the cropped image from the original image
idxI = 1+(i-1)*block_height:i*block_height;
idxJ = 1+(j-1)*block_width :j*block_width;
cropped_image(idxI,idxJ) = Im(idxI,idxJ);
%//imshow(cropped_image)
%// write the cropped image to the current folder
filename = sprintf('block_row%d_col%d.png',i,j);
imwrite(cropped_image,filename);
cropped_image(idxI,idxJ) = 0;
%// keep all the blocks in a 3D array if we want to use them later
img_stack(:,:,(i-1)*blocks_per_col+j);
end
end

Increase image contrast using look up table in MATLAB

I am trying to do some image processing for which I am given an 8-bit grayscale image. I am supposed to change the contrast of the image by generating a lookup table that increases the contrast for pixel values between 50 and 205. I have generated a look up table using the following MATLAB code.
a = 2;
x = 0:255;
lut = 255 ./ (1+exp(-a*(x-127)/32));
When I plot lut, I get a graph shown below:
So far so good, but how do I go about increasing the contrast for pixel values between 50 and 205? Final plot of the transform mapping should be something like:
Judging from your comments, you simply want a linear map where intensities that are < 50 get mapped to 0, intensities that are > 205 get mapped to 255, and everything else is a linear mapping in between. You can simply do this by:
slope = 255 / (205 - 50); % // Generate equation of the line -
% // y = mx + b - Solve for m
intercept = -50*slope; %// Solve for b --> b = y - m*x, y = 0, x = 50
LUT = uint8(slope*(0:255) + intercept); %// Generate points
LUT(1:51) = 0; %// Anything < intensity 50 set to 0
LUT(206:end) = 255; %// Anything > intensity 205 set to 255
The LUT now looks like:
plot(0:255, LUT);
axis tight;
grid;
Take note at how I truncated the intensities when they're < 50 and > 205. MATLAB starts indexing at index 1, and so we need to offset the intensities by 1 so that they correctly map to pixel intensities which start at 0.
To finally apply this to your image, all you have to do is:
out = LUT(img + 1);
This is assuming that img is your input image. Again, take note that we had to offset the input by +1 as MATLAB starts indexing at location 1, while intensities start at 0.
Minor Note
You can easily do this by using imadjust, which basically does this for you under the hood. You call it like so:
outAdjust = imadjust(in, [low_in; high_in], [low_out; high_out]);
low_in and high_in represent the minimum and maximum input intensities that exist in your image. Note that these are normalized between [0,1]. low_out and high_out adjust the intensities of your image so that low_in maps to low_out, high_in maps to high_out, and everything else is contrast stretched in between. For your case, you would do:
outAdjust = imadjust(img, [0; 1], [50/255; 205/255]);
This should stretch the contrast such that the input intensity 50 maps to the output intensity 0 and the input intensity 205 maps to the output intensity 255. Any intensities < 50 and > 205 get automatically saturated to 0 and 255 respectively.
You need to take each pixel in your image and replace it with the corresponding value in the lookup table. This can be done with some nested for loops, but it is not the most idiomatic way to do it. I would recommend using arrayfun with a function that replaces a pixel.
new_image = arrayfun(#(pixel) lut(pixel), image);
It might be more efficient to use the code that generates lut directly on the image. If performance is a concern and you don't need to use a lookup table, try comparing both methods.
new_image = 255 ./ (1 + exp(-image * (x-127) / 32));
Note that the new_image variable will no longer be of type uint8. If you need to display it again (say, with imshow) you will need to convert it back by writing uint8(new_image).

8 bit 2d array in matlab

I have a small problem in saving data in a array. I want to save data in the form 10001010 <- 8 bits in a 2d array containing 100 rows and 100 columns. what i do now is
a = rand(100,100);
a = a * 127; // <<- this is done to make it 8 bits
To confirm what i have done i did a imshow to display the image.
When a is multiplied by 127 most of the grayscale pixels has turned to white but before the multiplication step it showed a nice grayscale image.
a = rand(100,100); after a = a * 127;
If you want 8-bit representation it's actually 0->255 since image intensities are unsigned. Matlab checks which class the image is when using imshow, if it's a double, the range 0->1 is expected. Hence you need to cast the image to uint8 after multiplying for it to show properly.
a = rand(100,100);
a = a*255;
a = uint8(a);
imshow(a);

Resources