Changing widthstep of image opencv - opencv

I am working on project related to face recognition. For my program to work each image should satisfy the condition img->widthStep = 3 * img->width.
I am trying my code on database in which each image is of size 250x250. But the widthstep for the database is 752 hence the above condition does not satisfy. The function of widthstep is in accessing the pixel (http://opencv-users.1802565.n2.nabble.com/What-is-widthstep-td2679559.html).
Can I change the widthstep parameter to 750 without affecting other parameters of image?
Or else is there other way to achieve the condition zimg->widthStep = 3 * img->widthz?
I tried copying the 250x250 to 260x260 image as follows
Mat img1, img2=Mat::zeros(Size(260,260),CV_8UC3);
img1 = imread(ch);
img1.copyTo(img2.colRange(1,250).rowRange(1,250));
But it shows this error:
OpenCV Error: Assertion failed
(!fixedSize() || ((Mat*)obj)->size.operator()() =
= Size(cols, rows)) in unknown function, file D:\opencv2.4.5\opencv\modules\core
\src\matrix.cpp, line 1372
Can anyone help me out.
Thank you!

Since you are using term widthStep I guess you are using IplImage. IplImage was taken from Intel Performance Primitives (IPP) library. In order to have good performance it is required that widthStep of each row should be multiple of 4. To enforce this condition rows are padded with addition bytes. So as long as you are using IplImage you won't be able to have widthStep equal to 750 which is not multiple of 4.
OpenCV 1 was based on IplImage, but OpenCV 2 is based on Mat. Its been a years since IplImage was deprecated.
Mat has no such limitation. By default its step will be 750.
After edit of the question:
colRange(1,250) means 249 columns, not 250. Same for rowRange(1,250). When size of the image being copied is different from size of target image, target image is reallocated. But since colRange and rowRange return constant temporary image it can't be reallocated and the program crashes.

Related

What format should I use for a Opencv image if I need to access the underlaying data?

I've made a program that creates images using OpenCL and in the OpenCL code I have to access the underlaying data of the opencv-image and modify it directly but I don't know how the data is arranged internally.
I'm currently using CV_8U because the representation is really simple 0 black 255 white and everything in between but I want to add color and I don't know what format to use.
This is how I currently modify the image A[y*width + x] = 255;.
Since your A[y*width + x] = 255; works fine, then the underlaying image data A must be a 1D pixel array of size width * height, each element is a cv_8u (8 bit unsigned int).
The color values of a pixel, in the case of OpenCV, will be arranged B G R in memory. RGB order would be more common but OpenCV likes them BGR.
Your data ought to be CV_8UC3, which is the case if you use imread or VideoCapture. if it isn't that, the following information needs to be interpreted accordingly.
Your array index math needs to expand to account for the data's layout:
[(y*width + x)*3 + channel]
3 because 3 channels. channel is 0..2, x and y as you expect.
As mentioned in other answers, you'd need to convert this single-channel image to a 3-channel image to have color. The 3 channels are Blue, Green, Red (BGR).
OpenCV has a method that does just this, cv2.cvtColor(), this method takes an input image (in this case the single channel image that you have), and a conversion code (see here for more).
So the code would be like the following:
color_image = cv2.cvtColor(source_image, cv2.COLOR_GRAY2BGR)
Then you can modify the color by accessing each of the color channels, e.g.
color_image[y, x, 0] = 255 # this changes the first channel (Blue)

cuda 2D layered tex size: too large?

Following if the code to initiate a 3D array in cuda with size being width = 809; hight = 127; and number of layers = 2160;
cudaArray *sinor;
cudaExtent volumeSize = make_cudaExtent(809, 127, 2160);
const cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
gpuErrchk(cudaMalloc3DArray(&sinor, &channelDesc, volumeSize, cudaArrayLayered));
last line returns error "invalid argument" error. Is that because my number of layer is too large? I tried 1940, and it was fine. If I cannot do such a large number of layers, what is the work around here ? Thanks alot.
You can find the texture layer depth limit on the documentation here. As you inferred, the depth limit for layered textures and surfaces is 2048.
As was suggested in comments, your only real workaround here is to split your data over multiple texture objects and select between the objects based on index within the virtual combined textures.

Copy part of image to another image with EmguCV

I want to copy a center part (Rectangle) of my image to a completely white Mat (to the same position).
Code:
Mat src = Image.Mat;
Mat dst = new Mat(src.Height, src.Width, DepthType.Cv8U, 3);
dst.SetTo(new Bgr(255, 255, 255).MCvScalar);
Rectangle roi = new Rectangle((int)(0.1 * src.Width), (int)(0.1 * src.Height), (int)(0.8 * src.Width), (int)(0.8 * src.Height));
Mat srcROI = new Mat(src, roi);
Mat dstROI = new Mat(dst, roi);
srcROI.CopyTo(dstROI);
//I have dstROI filled well. CopyTo method is doing well.
//However I have no changes in my dst file.
However I'm getting only white image as a result - dst. Nothing inside.
What i'm doing wrong?
using EmguCV 3.1
EDIT
I have a dstROI Mat filled well. But there is a problem how to apply changes to original dst Mat now.
Changing CopyTo like this:
srcROI.CopyTo(dst);
causes that dst is filled now with my part of src image but not in the centre like i wanted
EDIT 2
src.Depth = Cv8U
As you suggested I check a value of IsSubmatrix property.
Console.WriteLine(dstROI.IsSubmatrix);
srcROI.CopyTo(dstROI);
Console.WriteLine(dstROI.IsSubmatrix);
gives output:
true
false
What can be wrong then?
Ancient question, I know, but it came up when I searched so an answer here might still be being hit in searches. I had a similar issue and it may be the same problem. If src and dst have different numbers of channels or different depths, then a new Mat is created instead. I see that they both have the same depth, but in my case, I had a single channel going into a 3 channel Mat. If your src is not a 3 channel Mat, then this may be the issue (it might be 1 (gray) or 4 channel (BGRA) for example).
According to the operator precedence rules of C# a type cast has higher priority than multiplication.
Hence (int)0.8 * src.Width is equivalent to 0 * src.Width, and the same applies to the other parameters of the roi rectangle. Therefore the line where you create the roi is basically
Rectangle roi = new Rectangle(0,0,0,0);
Copying a 0-size block does nothing, so you're left with the pristine white image you created earlier.
Solution
Parenthesize your expressions properly.
Rectangle roi = new Rectangle((int)(0.1 * src.Width)
, (int)(0.1 * src.Height)
, (int)(0.8 * src.Width)
, (int)(0.8 * src.Height));

Why does the Sobel function for edge detection fail to find the contour of a white square in a black background?

I tryed to apply to the image the following code in octave:
sq = imread("Square BW.jpg");
figure(1), imshow(Square);
cont1 = edge(sq,"Sobel");
figure(2), imshow(cont1);
The image I get is:
And a similar image appears if I use the Prewitt function. Can anyone explain to me what is happening? The problem is that I can't visualize the process only the result, so I can't understand why the code isn't working.
The problem seems to be how threshold is computed in Octave. You can see how Octave does it by looking at its source by entering type edge at the Octave prompt, or online (I'm not copying the exact code since the code is GPL -- although quite simple)
To get the border, you will need to set the threshold yourself (hopefully, in future versions of Octave's image package this will be fixed but at the moment it's Matlab incompatible since Matlab documentation on their default is unclear).
There's definitely a problem with the way the threshold is computed, however I wasn't able to find the correct value to use in this picture. After many attempts I found this code that seems to work perfectly:
sq = imread("Square BW.jpg");
maskSobel = fspecial("sobel");
mSobel = uint8(zeros(size(BW)));
for i = 0:3
mSobel += imfilter(sq, rot90(maskSobel, i));
end
figure(1), imshow(mSobel);
First we create the Sobel matrix/operator and a zero matrix the same size of the image Square BW. Then we rotate the Sobel matrix four times (by 90 degrees), in order filter the image in all directions (left-right, up-down, right-left and down-up), always adding the result to the mSobel matrix that was created.
Here's the final result:

How to get a line as a structuring element in openCv?

I have a binary image and I want to perform closing on that image with the line as structuring element.
The openCv api has a function getStructuringElement that takes the following parameters
Shape
Size
Anchor Point
I can pass CV_SHAPE_CUSTOM in the first parameter to create a new shape but where do I
pass the size and the values of my structuring element.
My line will be 10 pixels wide and 1 pixels in length basically {1,1,1,1,1,1,1,1,1,1}.
There is an old function createStructringElementEx but I don't want to use that as it involves a lot of conversion of datatype.
Is this what you want?
Size = Size(10,1)
Anchor Point = Point(-1,-1)
Got it . Thanks to the comment from Niko.
Create a matrix as
Mat line = Mat::ones(1,10,CV_8UC1);
//now apply the morphology close operation
morphologyEx(img, img, MORPH_CLOSE, line,Point(-1,-1));
This solved my problem.

Resources