opencv crop Mat, but allocating new ptr in the process - opencv

I am cropping an opencv Mat:
cv::Size size = img.size();
cv::Rect roi(size.width*/4., size.height/4.,size.width/2., size.height/.2);
img= img(roi);
I then use img.data pointer to create a vtkImageData (via vtkImageImport):
vtkSmartPointer<vtkImageImport> importer = vtkSmartPointer<vtkImageImport>::New();
importer->SetImportVoidPointer(img.data);
...
importer->Update();
vtkImageData* vtkImg = importer->GetOutput();
I don't get the expected result when I display the vtkImg. I've digged into opencv's code and the problem is that when creating the cropped data, opencv does not allocate a new pointer that is 4 times smaller but instead keeps the same already allocated block, advances the pointer upstream and flags the new img variable as not continuous. Therefore my vtk image still imports data from the original uncropped Mat. I know I could import the full image to vtkImageData and then do the cropping with a vtk filter but I would prefer not to.
Is there a way with opencv to obtain a cropped image that is "physically" cropped (with a newly allocated data pointer)?
Thank you

I believe you are looking for cv::Mat::clone(). It makes a deep copy of the underlying image data and returns a cv::Mat object which contains said data.
You would then change the line
img= img(roi);
to
img = img(roi).clone();
After which img contains only the cropped data.

Related

Texture atlas to texture array via PIXEL_UNPACK_BUFFER

I have two questions:
First, is there any more direct, sane way to go from a texture atlas image to a texture array in WebGL than what I'm doing below? I've not tried this, but doing it entirely in WebGL seems possible, though four-times the work and I still have to make two round trips to the GPU to do it.
And am I right that because buffer data for texImage3D() must come from PIXEL_UNPACK_BUFFER, this data must come directly from the CPU side? I.e. There is no way to copy from one block of GPU memory to a PIXEL_UNPACK_BUFFER without copying it to the CPU first. I'm pretty sure the answer to this is a hard "no".
In case my questions themselves are stupid (and they may be), my ultimate goal here is simply to convert a texture atlas PNG to a texture array. From what I've tried, the fastest way to do this by far is via PIXEL_UNPACK_BUFFER, rather than extracting each sub-image and sending them in one at a time, which for large atlases is extremely slow.
This is basically how I'm currently getting my pixel data.
const imageToBinary = async (image: HTMLImageElement) => {
const canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
const context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
const imageData = context.getImageData(0, 0, image.width, image.height);
return imageData.data;
};
So, I'm creating an HTMLImageElement object, which contains the uncompressed pixel data I want, but has no methods to get at it directly. Then I'm creating a 2D context version containing the same pixel data a second time. Then I'm repopulating the GPU with the same pixel data a third time. Seems bonkers to me, but I don't see a way around it.

EmguCV - Mat is not empty after creating

I'm working currently with EmguCV and I need empty Mat. But apparently when I create it, the new Mat has sometimes some random values which I do not want.
I'm creating it like that:
Mat mask =new Mat(mainImg.Size,Emgu.CV.CvEnum.DepthType.Cv8U,1);
And when I display the 'mask' it looks like that:
It should be completely black but as you can see there is some trash which cause me trouble in reading the mat.
Does anyone know why it is like that? Maybe is there a clever way to clear the Mat?
Thanks in advance!
To create an empty Mat just use the code below.
Mat img = new Mat();
If you want to make it a specific size, use the following code. In your question above, you were choosing a depth type of 8U, which might be contributing to your low quality of an image. Here I choose a depth type of 32F, which should increase the quality of the new mask image. I also added 3 channels instead of 1, so you can have full access to the Bgr color space.
Mat mask = new Mat(500, 500, DepthType.Cv32F, 3);
Mat objects are great because you don't need to specify the size or depth of the image beforhand. Simmilarly, if you want to use an Image instead, you can use the code below.
Image<Bgr, byte> img = new Image<Bgr, byte>(500, 500);
You will need to add some dependencies, but this is the easiest and my preferred way of doing it.

Cannot save image filtered in OpenCV

I am trying to save image after applying filter, but after saving operation on my disk I have not dst_1, but img.
img = cv2.imread(images[14], 1)
kernel = np.ones((5,5), np.float32)/25
dst_1 = cv2.filter2D(img, -1, kernel)
cv2.imwrite("path/f.jpg", dst_1)
When I am using imshow after applying filter, I see what I expected to see - filtered image.
Does anybody know, what is the reason of this imwrite behavior or where is my mistake?
I believe the problem is not with the way you are saving the file, but rather your filter is not doing what you think it is doing, thus it looks no different to the image you are saving.
OpenCV opens the image in BGR format, and the second image you showed in your comment is the same image, but in RGB format, OpenCV has a function that can do this for you, so please try the below code:
import cv2
import numpy as np
img = cv2.imread(images[14], 1)
dst_1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
cv2.imwrite("path/f.jpg", dst_1)
This should achieve the output you are looking for, hope it helps!

How to Do Live FFT of sub-area (ROI) of a Image using DigitalMicrograph script

I mean both the sub-area change and the data change will trigger the FFT process, so I can see sub-area FFT of a Live Image.
You can simply use the command NewLiveFFT for this.
Below is an example script. Note that if a ROI selection is present on the image, it will be used. Otherwise the whole image is used. You can, of course, create a specific ROI via script and add it as well.
number kRasterDisplay = 1
image img
if (!GetFrontImage(img)) exit(0)
imageDisplay disp = img.ImageGetImageDisplay(0)
if ( kRasterDisplay != disp.ImageDisplayGetDisplayType() ) exit(0)
ROI sel = disp.ImageDisplayGetRoi(0)
NewLiveFFT(disp,sel,0)
Note that LiveFFTs will automatically stop if the data type of the source image changes, or if the source image is closed. You can also not resize the ROI of a LiveFFT. It would be possible to create a script which allows ROI resize, but then you would have to use ROI-listeners and code all the according links and FFTs yourself.

issue while writing cvGetImage using cvMat

I am facing a problem while writing image from cvMat.
This is what I have done.
IplImage* low_threshold_mask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
CvMat* labelMat = cvCreateMat(low_threshold_mask->height,low_threshold_mask->width,CV_32F);
/* I populate elements of labelMat inside a function. Its done like this: cvmSet(labelMat,r,c,label); // where label is of type long */
To check the values I dump each pixel value in a text file and also dump the image.
IplImage* labelImg;
IplImage imageHeader;
labelImg = cvGetImage(labelMat, &imageHeader);
Now when I cross-check pixel intensity with corresponding value in dumped text file, I find mis-match. I feel I have got correct values in text file but wrong ones in image.
Can anyone help in figuring out the mistake?
---------------------New addition-------------------
I am still facing the problem. I have uploaded my programs. I will explain where exactly I am facing the error.
Libraries used: Along with openCV, I am using disjoint_sets of boost library.
Basically I am doing connected component labeling.
For debugging purpose, for 20th frame, I have dumped the label info of each pixel both in a)text file as well b) an image with intensity levels same as the final label of the pixels. So i am expecting the values same in both text and image. But that's not happening. And I am unable to figure out why. The text files shows the correct values but not the image. I am checking pixel values of image in Matlab(i had taken care of indices in matlab starts with 1 not 0).
My text files
a) (frame20final.txt) gets populated in GrimsonGMM.cpp/ConCompLabeling().
b) (frame20image.txt) gets populated in main.cpp
My dumped image(frame-ccs.jpg) gets populated in main.cpp.
Both the text files get same values. So there must be some mistake in writing the image from CvMat.
Test Video: person15_walking_d1_uncomp.avi
You can try with any other video also.
Thanks in advance,
Kaushik
I understood why I was getting the error. I was dumping in .jpg image which was doing compression. This was resolved when I used .png
Your question its so easy.
You want to work with CvMat and after do operations with CvMat you want to plot your CvMat like it was an image.
You must create imageHeader, something like this.
CvMat* mat = cvCreateMatHeader(rows, cols, type);
mat->step = 4 * (mat->cols * CV_ELEM_SIZE1(mat->type) * CV_MAT_CN(mat->type) / 4 + 1);//critical
cvCreateData(mat);
In OpenCV 2.0 and below C++ interface it's not really necessary to change from Mat to IplImage.
You can plot your image using cvShowImage and if you want to convert intoIplImage
just do a easy cast IplImage *img = labelMat;

Resources