how to get an average image from multiple images in C# - image-processing

i want to create an average image from a set of multiple images (around 100) of same size in C#. Is it possible to do the same using EMGUCV, OPenCV or any other method without using any library. Please help me out or share the code if possible

With OpenCV in C++, here is an example:
Mat acc(img.size(), CV_64F, Scalar(0)); // all black, *double* image
accumulate(img1,acc);
accumulate(img2,acc);
accumulate(img3,acc);
accumulate(img4,acc);
//...
accumulate(img100,acc);
Mat avg;
acc.convertTo(avg, CV_8U, 1.0/100); // back to u8 land, divide by count
It should be quite trivial to port it to C#.

Related

Converting a Matrix to a Vector in openCV

I have an image 16x16 pixel image , how can I put it in a matrix 1x256 pixel and then convert it back to a 16x16 pixel Using opencv ?
I tried reshape but it didn't succeed as when i make cout<< image.cols << image.rows give me the same number which is 16,16 also sometimes the image is not continuous so reshape won't work
Btw I need it in coding a neural network classifier.
// create matrix for the result
Mat image1x256(Size(256,1), image.type());
// use reshape function
Mat image16x16 = image1x256.reshape(image.channels(), 16);
// copy the data from your image to new image
image.copyTo(image16x16);
Since image16x16 and image1x256 are just different pointers to same data, then copying the data to one of them will actually change both.
Note that reshape function creates a new header (i.e. new smart pointer) that may be used instead of old one, but it is not changing properties of the original header that still exist and can be used.

Multidimensional cv::Mat initialization and display

Being a Matlab/Python guy and a novice in C++, I'm having major frustration moving to OpenCV in C++ for image processing purposes. I'm working with Kinect v2 so there is only one Windows example I found online which I'm modifying.
This example gives the depthMap as a cv::Mat and I've calculated surface normals on this depth image taken from a kinect v2. This surface normal image contains the i,j,k vector components (3 channels) per row,col element and I'm trying to visualize this surface normal image (3-D float matrix) as an RGB image. This is really easy to do in matlab since you just do an imshow(normMap) and it shows an RGB (ijk) image with the color specifying the orientation of the normal.
I'm trying to do a similar thing in C++. Since I'm using opencv, I decided to use the cv::Mat to store the ijk channels per pixel and I initialized the normal matrix (lets call it normMat) to a CV_32F matrix as follows:
int sizes[3] = { height, width, 3 };
cv::Mat normMat(3, sizes, CV_32F, cv::Scalar::all(0));
However, if I debug, the dims (normMat.rows and normMat.cols) are showing -1, so I don't know whether my initialization is bad or if I missed something, or whether it's normal.
I'm storing the surface normal components as:
normMat.at<float>(i, j, 0) = fVec3[0];
normMat.at<float>(i, j, 1) = fVec3[1];
normMat.at<float>(i, j, 2) = fVec3[2];
And they seem to be getting stored correctly as I've verified that in debug (using normMat.at<float>(i,j,k)).
Then I'm trying to display the image as:
normMat.convertTo(normColorMap, CV_8UC3, 255.0 / (4000), 255.0 / 500);
cv::imshow("Normals", normColorMap);
But the second line throws an exception:
OpenCV Error: Assertion failed (p[-1]
<= 2) in cv::MatSize::operator.....
I also tried displaying normMat directly which throws the same exception. Which means that there's obviously something wrong with displaying a 3 channel image as a 3D matrix, or converting it to a 2D-3 Channel Mat. I also tried initializing normMat as
cv::Mat normMat(height, width, CV_32FC3, cv::Scalar::all(0));
But I'm having issues adding data to the 3 channels of a "2D 3 channel matrix" (CV_32FC3), if I may say it this way.
All I want to do is display this normMat as an RGB image. Any inputs,suggestions are highly appreciated. Thanks!

OpenCV MedianBlur function crashing when Mat is of type CV_32S

I am working on Demosaicing a Bayer pattern to RGB image without using OpenCV's direct conversion function. I have used Bilinear interpolation and got it to work, but I want to improve the quality by using The Freeman Method. This method requires Median Filter. OpenCV has medianBlur function which does that. But I am having trouble using this function. When the cv::Mat to which I apply medianBlur is of type CV_8UC1 then it works, but if it is of type CV_32S, then it does not work.
This does NOT work:
redGreenMedian.create(input.size(), CV_32S);
blueGreenMedian.create(input.size(), CV_32S);
blueMinusGreen.create(input.size(), CV_32S);
redMinusGreen.create(input.size(), CV_32S);
for(int i = 1; i <= 3; i += 2)
{
cv::medianBlur(redMinusGreen, redGreenMedian, i);
cv::medianBlur(blueMinusGreen, blueGreenMedian, i);
}
If I change all CV_32S to CV_8UC1 then it works. On debugging I found that it crashes in the second iteration only not in first one. However, I need it to run for both iterations. This does NOT work when written separately too:
cv::medianBlur(redMinusGreen, redGreenMedian, 3);
As an aside, I do not have to use CV_32S, but I need the ability to store negative numbers in the matrices.
NOTE: I have tried making all numbers in the matrices positive and then use medianBlur, but it still did not work.
All help is appreciated. Thanks in advance.
The OpenCV documentation seems to be very clear:
src – input 1-, 3-, or 4-channel image; when ksize is 3 or 5, the image depth should be CV_8U, CV_16U, or CV_32F, for larger aperture sizes, it can only be CV_8U.
As you need to cater for signed values, I think your best option is to use CV_32F.
Also, the documentation says
ksize – aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7
Your loop applies sizes of 1 and 3 (if I read your code correctly), the first of which is invalid, which possibly explains why your first iteration doesn't crash (because it fails earlier).

OpenCV default storage format

What is the default (Pixel) storage format used by OpenCV ?
I know it is BGR but is it BGR32 ? BGR16 ?
Is it Packed or Planar ?
Can you suggest me a way to find it out?
Thank you for your help.
[EDIT] Context : Actually I am trying to use OpenCV with another library called MIL (Matrox Imaging Library). I need to grab an Image with MIL and then convert it to an OpenCV Image. That is why I need to know the default pixel format, to configure MIL.
The image format is set by the flag when you create the image eg CV_8UC3 means 8bit pixels, unsigned, 3colour channels. In a colour image the pixel order is BGR, data is stored in row order.
The data isn't packed at the pixel level - it's 3bytes/pixel (BGRA is an option on some of the GPU calls).
Data may be packed at the line level, if the number of pixels in a row * the number of bytes/pixel isn't a multiple of 4 then the data is padded with zero to the next 32bit boundary. The call mat.ptr(n) returns a pointer to the start of the 'n' th row
Note that you can share memory with another comaptible image format by passing the data pointer from the MIL image to the ctor of the cv::Mat
It depends on the way you are managing the image: have you loaded it from a file with imread for example?
Have a look at imread here, with a colour jpeg for example you'll have a 3 channel format, 24 bits overall. Can you be more specific?
I do not know if it's useful, but I had a similar issue when converting an image from Android Bitmap (passed to OpenCV as a byte array RGBA8888) to OpenCV image (BGR888).
Here is how I've solved it.
cv::Mat orig_image1(orig_height, orig_width, CV_8UC4, image_data);
int from_to[] = { 0, 2, 1, 1, 2, 0};
cv::Mat image(orig_height, orig_width, CV_8UC3);
cv::mixChannels(&orig_image1, 1, &image, 1, from_to, 3);
orig_image1.release();

Compare histograms of specific areas of two images? OpenCV

Basically, I want to be able to compare two histograms, but not of whole images just specific areas. I have image A and have a specific rectangular region on it that I want to compare to another image B. Is there a way to get the histogram of a definable rectangular region on an image? I have the x y position of the rectangular area, as well as it's width and height, and want to get its histogram. I'm using opencv with python.
Sorry if that isn't very clear :(
(I'm setting up a program that takes a picture of a circuit board, and checks each solder pad for consistency with an image of a perfect board. If one pad is off, the program raises a flag saying that specific pad is off by x percent, not the whole board.
Note: The following is in C++ but I think it is not hard to find the equivalent functions for python.
You can find the histogram of an image using this tutorial. So for example for the lena image we get:
In your case, since you have the rectangle coordinates, you can just extract the ROI of the image:
// C++ code
cv::Mat image = cv::imread("lena.png", 0);
cv::Rect roiRect = cv::Rect(150, 150, 250, 250);
cv::Mat imageRoi = image(roiRect);
and then find the histogram of just the ROI with the same way as above:
Is this what you wanted (in theory at least) or I misunderstood?

Resources