conversion of matlab code to opencv code - c++

I have a matlab code in which the image x has 512*512 size were M=512 and N=512 next step is this
r=x(:, 2:N) - x(:, 1:(N-1));
d= mean2(abs(r(:, 8:8:8*(floor(N/8)-1))));
a= (8*mean2(abs(r)) - d)/7;
Now I have to convert this steps in to opencv code so I am stuck with logic
cv::Mat scrImage =imread(argv[1],CV_LOAD_IMAGE_ANYCOLOR); // Read the file
cv::Mat dst(scrImage.size(),CV_64FC3);//Image double
int nrows = dst.rows;
int ncols = dst.cols*dst.channels();
for(int j=0;j<nrows;j++){
for(int i=0;i<ncols;i++)
{
}}
Any idea on this? Thanks in advance

There are many ways to do this. Most clean way would be setting ROI (Region of Interest) and then applying matrix operations. Something like:
subtract(x(Rect(1,0,NumCols-1,NumRows)),x(Rect(0,0,NumCols-1,NumRows),R)
singleLineMask = Mat(1,NumCols,CV_8U)
for (int i=1;i<NumCols;i++)
singleLineMask.at<int>(1,i)=1;
repeat(singleLineMask,NumRows,1,MaskImage)
d=mean(R,MaskImage)
a=(8*mean(abs(R))-d)/7
assuming you create R and compute NumRows,NumCols prior to this operation and allocate MaskImage.

Related

Asigning pixel intensities to an unitialized Mat matrix using pointer

I try to extract the region of interest (ROI) in a Matrix in OpenCV. It can be easy to do by cv:Rect, e.g., im_roi = im(Rect(x,y, width, height)). But I prefer to get the data directly from the memory using pointers, which is presumably more efficient. Here below are my codes:
Mat im_roi; //the desired matrix holding ROI of im, uninitialized
uchar* im_roi_data = im_roi.data;
uchar* im_data = im.data;
int xstart = x;
int xend = xstart + width;
int ystart = y;
int yend = ystart + height;
for(ii=ystart; ii<yend; ii++)
{
for(jj=xstart; jj<xend; jj++) //the typo 'jj<xstart' was corrected
{
*im_roi_data++ = *im_data++;
*im_roi_data++ = *im_data++;
*im_roi_data++ = *im_data++;
}
im_data +=3*(im.cols-width);
}
The above for-loop codes however do not proceed. I feel the problem may be due to the uninitialized im_roi.
I think your second for loop needs to be:
for(jj=xstart; jj<xend; jj++)
As Mark Setchell noted it is not the only problem with your code, but yes you must initialize im_roi before accassing its pixels.
Using memcpy to copy content of whole row will be much more effecient then copying data pixel by pixel.
Writing im(Rect(x,y, width, height)).copyTo(im_roi); will be the cleanest AND fastest method of coping ROI (and in that case you don't need to initialize im_roi).

operations with vectors and xml file for SVM on c++

i'm writing a code for SVM detection using Opencv. Actualy, for the training data, i've two matrix (positive and negative features) creating by:
const size_t N=12;
std::vector<std::array<int,N>> matrixForTrainingDataPos;
std::vector<std::array<int,N>> matrixForTrainingDataNeg;
populated with 12 features for each image. I've 100 positive images and 140 negative images and then matrixForTrainingDataPos is [100][12] and matrixForTrainingDataNeg[140][12]. Now i have to concatenate them to get:
float trainingData[240][12] = {--------};
Mat trainingDataMat(240, 12, CV_32FC1, trainingData);
I tried with some operation as pusk_back but I did not succeed. I am , however, managed to build an array of 240 elements for the labeling: 100 with 1 and 140 with -1 using two for cicle. Next step is save a trainingData on xml file so that once launched the program if there is no file creates it , avoiding all the processing of trainingData if you have already made
can you help me?
tanks!
int count = 0;
for(int i = 0; i < matrixForTrainingDataPos.size(); i++)
{
for (int j = 0; j < N; j++)
{
trainingData[count][j] = matrixForTrainingDataPos[i][j];
}
count++;
}
/* copy negative sample matrix data */
it works. But the compiler returned an exception for me so I had to declare ad unsigned the i j variables: for (unsigned i=0......
for my second question? how i save and load this matrix on xml file, on first passage, to avoid in the next steps to be recalculated?

pointcloud data to mat data

I have to convert ply data to mat data. For this i have used plyreader of pcl and convert in into point cloud and now my next step is to convert it into mat data from point cloud.
I guess the point cloud which i obtained from plyreader is unorganised. I have been trying to extract the xyz values of point cloud and then copying it in at data.
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
// create a new point cloud (POINTXYZ)
pcl::PLYReader reader;
reader.read(filename,*cloud); // read the ply file
cv::Mat output;
//...
output = cv::Mat(1,cloud->points.size(),CV_32FC3);
for(size_t i=0; i<cloud->points.size();++i)
{
int m = cloud->points[i].x;
int n = cloud->points[i].y;
int l = cloud->points[i].z;
float x0;
float x1;
float x2;
output.at<cv::Vec3f>(x0,x1,x2)= cv::Vec3f(m,n,l);
}
I know it is wrong. I found one post about this but that is for organised cloud Link is here -->
Visit [pointcloud to mat]
Coversion from PointCloud to Mat
I am new to this field. If anyone know or could help!!!
Thanks in advance
It should be:
output.at<cv::Vec3f>(1,i)[0] = cloud->points[i].x; //(1,i) is (row,col)
output.at<cv::Vec3f>(1,i)[1] = cloud->points[i].y; // [1] is y float
output.at<cv::Vec3f>(1,i)[2] = cloud->points[i].z;
cv::Size sz;
sz= cv::Size(cloud->width,cloud->height);
cv::Mat output(sz,CV_32FC3);
cvWaitKey(50);
for (int j=0; j<output.rows;++j)
{
for(int i= 0; i<output.cols;++i)
{
output.at<cv::Vec3f>(1,i)[0] = cloud->points[i].x;
output.at<cv::Vec3f>(1,i)[1] = cloud->points[i].y;
output.at<cv::Vec3f>(1,i)[2] = cloud->points[i].z;
}}
There is no error in the code and runs properly but still at the cv:: Mat output, the values are not copying and giving some absurd result. Does anyone know the mistake or how to get values at output as cvmat data only.

Need a faster way to convert a cv::Mat into 1 dimensional vector form

I have a for loop the takes an OpenCV Mat object of n x n dimensions, and returns a Mat object of n^2 x 1 dimensions. It works, but when I time the method it takes between 1 and 2 milliseconds. Since I am calling this method 3 or 4 million times its taking my program about an hour to run. A research paper I'm referencing suggests the author was able to produce a program with the same function that ran in only a few minutes, without running any threads in parallel. After timing each section of code, the only portion taking >1 ms is the following method.
static Mat mat2vec(Mat mat)
{
Mat toReturn = Mat(mat.rows*mat.cols, 1, mat.type());
float* matPt;
float* retPt;
for (int i = 0; i < mat.rows; i++) //rows
{
matPt = mat.ptr<float>(i);
for (int j = 0; j < mat.row(i).cols; j++) //col
{
retPt = toReturn.ptr<float>(i*mat.cols + j);
retPt[0] = matPt[j];
}
}
return toReturn;
}
Is there any way that I can increase the speed at which this method converts an n x n matrix into an n^2 x 1 matrix (or cv::Mat representing a vector)?
that solved most of the problem #berak, its running a lot faster now. however in some cases like below, the mat is not continuous. Any idea of how I can get an ROI in a continuous mat?
my method not looks like this:
static Mat mat2vec(Mat mat)
{
if ( ! mat.isContinuous() )
{
mat = mat.clone();
}
return mat.reshape(1,2500);
}
Problems occur at:
Mat patch = Mat(inputSource, Rect((inputPoint.x - (patchSize / 2)), (inputPoint.y - (patchSize / 2)), patchSize, patchSize));
Mat puVec = mat2vec(patch);
assuming that the data in your Mat is continuous, Mat::reshape() for the win.
and it's almost for free. only rows/cols get adjusted, no memory moved. i.e, mat = mat.reshape(1,1) would make a 1d float array of it.
Seeing this in OpenCV 3.2, but the function is now mat.reshape(1).

How to improve sorting pixels in cvMat?

I am trying to sort pixel values of an image (example 80x20) from lowest to highest.
Below is the some code:
bool sortPixel(int first, int second)
{
return (first < second);
}
vector<int>vect_sortPixel;
for(int y=0; y<height; y++)
{
for(int x=0; x<width; x++)
{
vect_sortPixel.push_back(cvGetReal2D(srcImg, y, x));
sort(vect_sortPixel.begin(), vect_sortPixel.end(), sortPixel);
}
}
But it takes quite long time to compute. Any suggestion to reduce the processing time?
Thank you.
Don't use getReal2D. It's quite slow.
Convert image to cv::Mat or Mat. Use its data pointer to get the pixel values. Mat.data() will give you pointer to the original matrix. Use that.
And as far as sorting is concerned, I would advise you to first make an array of all the pixels, then sort it using Merge sort (time complexity O(n log n))
#include<opencv2/highgui/highgui.hpp>
#include<stdio.h>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("filename.jpg",CV_LOAD_IMAGE_COLOR);
unsigned char *input = (unsigned char*)(img.data);
int i,j,r,g,b;
for(int i = 0;i < img.cols;i++){
for(int j = 0;j < img.rows;j++){
b = input[img.cols * j + i] ;
g = input[img.cols * j+ i + 1];
r = input[img.cols *j + i +2];
}
}
return 0;
}
Using this you can access pixel values from the main matrix.
Warning: This is not how you compare it. I'm suggesting that by using something like this, you can access pixel values.
Mat.data() gives you pointer to the original matrix. This matrix is a 1 D matrix with all the given pixel values.
Image => (x,y,z),(x1,y1,z1), etc..
Mat(original matrix) => x,y,z,x1,y1,z1,...
If you still have some doubts regarding how to extract data from Mat, visit this link OpenCV get pixel channel value from Mat image
and here's a link regarding Merge Sort http://www.cplusplus.happycodings.com/Algorithms/code17.html
There are few problems in your code:
As Froyo already said you use cvGetReal2D which is actually not very fast. You have to convert your cvMat to cv::Mat. To do this there's cv::Mat constructor:
// converts old-style CvMat to the new matrix; the data is not copied by default
Mat(const CvMat* m, bool copyData=false);
And after this use direct pixels acces as mentioned in this SO question.
Another problem is that you use push_back which actually also not very fast. You know the size of array, so why don't you allocate needed memory at the beginning? Like this:
vector<int> vect_sortPixel(mat.cols*mat.rows);
And than just use vect_sortPixel[i] to get needed pixel.
Why do you call sort in the loop? You have to call it after loop, when array is already created! Default STL's sort should work fast:
Complexity
Approximately N*logN comparisons on average (where N is
last-first). In the worst case, up to N^2, depending on specific
sorting algorithm used by library implementation.