Comparing pixels in alpha-trimmed filter - c++

I have the following problem. I have written code for alpha-trimmed filter in opencv library. I think that it is properly constructed but I don't know how to compare two 3 channels pixels during sorting a 'window with pixels'. In my code it is done but comparing two but it is impossible for vectors. I assume that i should compare it one channel and after second and so on. Have you any hints for me, or could you propose some modifications in my code. This is my code.
int alphatrimmed(Mat img, int alpha)
{
Mat img9 = img.clone();
const int start = alpha;
const int end = 9 - alpha;
//going through whole image
for (int i = 1; i < img.rows - 1; i++)
for (int j = 1; j < img.cols-1; j++)
{
int k = 0;
Vec3b element[9];
//selecting elements
for (int m = i - 1; m < i + 2; m++)
for (int n = j - 1; n < j + 2; n++)
element[k++] = img.at<Vec3b>(m*img.cols + n);
for (int i = 0; i < end; i++)
{
int min = i;
for (int j = i + 1; j < 9; j++)
if (element[j] < element[min])
min = j;
Vec3b temp = element[i];
element[i] = element[min];
element[min] = temp;
}
const int result = (i - 1)*(img.cols - 2) + j - 1;
img9.at<Vec3b>(result) = element[start];
for (int j = start + 1; j < end; j++)
img9.at<Vec3b>(result) += element[j];
img9.at<Vec3b>(result) /= 9 - alpha;
}
namedWindow("AlphaTrimmed Filter", WINDOW_AUTOSIZE);
imshow("AlphaTrimmed Filter", img9);
return 0;
}
Thank you for your time spent on solving my problem.

Related

C++: Reshape vector to 3D array

Edit: I have uploaded the vector to Drive as a text file, in case anyone want to have a look: https://drive.google.com/file/d/0B0wsPU8YebRQbDUwNFYza3ljSnc/view?usp=sharing
I'm trying to reshape my vector h into a 3D array. h contains 295788 elements. In this case height = 314, width = 314 and depth = 3.
Basically what I'm trying to do is what MATLAB does with its reshape function.
h = reshape(h, height, width, depth)
This is my attempt so far, but when I print it all I see is zeroes, which is not right. I have double checked that h contains the numbers I'm expecting.
vector<vector<vector<double> > > array3D;
int height = 314, width = 314, depth = 3;
// Set up sizes
array3D.resize(height);
for (int i = 0; i < height; ++i) {
array3D[i].resize(width);
for (int j = 0; j < width; ++j)
array3D[i][j].resize(depth);
}
for (int i = 0; i < height; i++)
{
array3D[i][0][0] = h[i];
for (int j = 0; j < width; j++)
{
array3D[i][j][0] = h[i+j];
for (int k = 0; k < depth; k++)
{
array3D[i][j][k] = h[i+j+k];
}
}
}
Printing:
for (vector<vector<vector<double>>>::const_iterator i = array3D.begin(); i != array3D.end(); ++i)
{
for (vector<vector<double>>::const_iterator j = i->begin(); j != i->end(); ++j)
{
for (vector<double>::const_iterator k = j->begin(); k != j->end(); ++k)
{
cout << *k << ' ';
}
}
}
So my question is, how do I convert my vector into a 3D array properly?
I managed to do this by using Eigen::Tensor as suggested by Henri Menke. I ended up creating an array for the initial 314x314x3 matrix, and then another one for the 300x300x3 matrix. It's neither fast nor pretty, but for now that is what I could come up with. Looks like this.
For clarification: margin is calculated further up in the code, but in this example with the 314x314x3 matrix it's margin=7. h is a vector with 295788 elements. nrh=314, nch=314 and nradii=3.
Tensor<int, 3> t(nrh, nch, nradii);
int counter = 0;
for (int k = 0; k < nradii; k++)
{
for (int col = 0; col < nch; col++)
{
for (int row = 0; row < nrh; row++)
{
t(row, col, k) = h[counter];
counter += 1;
}
}
}
int height = nrh - margin * 2;
int width = nch - margin * 2;
int depth = nradii;
Tensor<int, 3> out(height, width, depth);
int count1 = 0, count2 = 0, count3 = 0;
for (int k = 0; k < depth; k++)
{
for (int j = margin; j < nch - margin; j++)
{
for (int i = margin; i < nrh - margin; i++)
{
out(count1, count2, count3) = t(i, j, k);
count1 += 1;
}
count1 = 0;
count2 += 1;
}
count2 = 0;
count3 += 1;
}
Edit: Solution #2 with Tensor.slice()
int height = nrh - margin * 2;
int width = nch - margin * 2;
int depth = nradii;
Tensor<int, 3> tensor(height, width, depth);
DSizes<ptrdiff_t, 3> indices(margin, margin, 0);
DSizes<ptrdiff_t, 3> sizes(height, width, nradii);
tensor = t.slice(indices, sizes);
How about:
array3D[i][j][k] = h[i*(depth*width)+j*depth+k];
That may or may not be scanning the vector in the correct order.
Notice how when the index k resets the index j increments so you move on exactly one until the index j resets in which case i increments and the same. It's easy to show this calculation reads every element exactly once.
I'd normally expect a width, height then depth and you're scanning in the opposite order!
Footnote: Depending on the application is may be worthwhile to just access the vector using this approach. In general it turns out to be faster than accessing a vector of vectors of vectors. That can be relevant when dealing with massive arrays.
Actually, your the structure of your code is already ok, however, there are two mistakes:
The lines
array3D[i][0][0] = h[i];
and
array3D[i][j][0] = h[i+j];
are pointless. You are overwriting those entries later on with the line
array3D[i][j][k] = h[i+j+k];
The index calculation for h[] is wrong: You must multiply the row index by the length of a row before adding the cell index. The assignment should look like this:
array3D[i][j][k] = h[(i*width+j)*depth+k];
Otherwise, you will get the same result for (i, j, k) == (3, 2, 1) as for (i, j, k) == (1, 3, 2), which is obviously wrong. In the index calculation above, I have assumed that k is the fastest changing dimension. If that is not the order in which your data is stored in h, you need to change the positions of i, j, and k and adjust the factors accordingly.
Putting this together, your assignment loop should read:
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
for (int k = 0; k < depth; k++) {
array3D[i][j][k] = h[(i*width+j)*depth+k];
}
}
}
Slightly off-topic:
If you were using C instead of C++, you could "simply" do this:
size_t dataSize;
//Create a real 3D array with the dimensions (height, width, depth).
double (*array3D)[width][depth] = malloc(dataSize = height*sizeof(*array3D));
//Copy over the data from the file.
memcpy(array3D, h, dataSize);
//Print the array contents:
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
for (int k = 0; k < depth; k++) {
printf("%d ", array3D[i][j][k]);
}
}
}
This uses a real 3D array instead of an array of pointers to arrays of pointers to arrays of doubles (which is roughly what a vector<vector<vector<double>>> is). However, this cannot be done in C++ as C++ does not allow for array types with dynamic sizes as C does.

how to improve performance of 2d array in C++

I have a low-level function that will be called millions of times, so it should be very efficient. When I use "gprof" in Linux, I found that a part of the code takes 60% of the total computation of the function (the rest part is to solve the roots of a cubic equation). Here Point is a data structure has x and v, which will be converted to a matrix for later use. The idea is to subtract each row by the first row. The code shows like below
double x[4][3] = {0}, v[4][3] = {0};
for (int i = 0; i < 4; ++i){
for (int j = 0; j < 3; ++j){
v[i][j] = Point[i]->v[j];
x[i][j] = Point[i]->x[j];
}
}
for (int i = 1; i < 4; ++i){
for (int j = 0; j < 3; ++j){
v[i][j] = v[0][j] - v[i][j];
x[i][j] = x[0][j] - x[i][j];
}
}
Can anyone show me the problem of this code? Why it performs so badly?
You can do it all in one pass:
double x[4][3] = {
{ Point[0]->x[0], Point[0]->x[1], Point[0]->x[2] }
};
double v[4][3] = {
{ Point[0]->v[0], Point[0]->v[1], Point[0]->v[2] }
};
for (int i = 1; i < 4; ++i){
for (int j = 0; j < 3; ++j){
x[i][j] = x[0][j] - Point[i]->x[j];
v[i][j] = v[0][j] - Point[i]->v[j];
}
}
You could even take that to the next level and put the entire thing into the initializers for x and v.
Or, if x and v in Point are each contiguous arrays:
double x[4][3], v[4][3]; // no init
// fill entire arrays
for (int i = 0; i < 4; ++i){
memcpy(x[0], Point[0]->x, sizeof(x[0]));
memcpy(v[0], Point[0]->v, sizeof(v[0]));
}
for (int i = 1; i < 4; ++i){
for (int j = 0; j < 3; ++j){
x[i][j] -= Point[i]->x[j];
v[i][j] -= Point[i]->v[j];
}
}

window operation by Pointer of image

If we access pixel by a pointer using step and data of Mat Image. see example below
int step = srcimg.step;
for (int j = 0; j < srcimg.rows; j++) {
for (int i = 0; i < srcimg.cols; i++) {
//this is pointer to the pixel value.
uchar* ptr = srcimg.data + step* j + i;
}
}
Question:
How can we perform 3x3 weighted avg operations with image step by a pointer?
thanks
You mustn't use data field in opencv because memory is not allways continuous. you can check this using isContinuous() method.
Now you can do like this (image type is CV_8UC1)
for (int i = 1; i < srcimg.rows-1; i++)
{
for (int j = 1; j < srcimg.cols-1; j++)
{
int x=0;
for (int k=-1;k<=1;k++)
{
uchar* ptr=srcimg.ptr(k+i)+j-1;
for (int l=-1;l<=1;l++,ptr++)
x +=*ptr;
}
}
}
image border are not processed. Now if you want to blur an image use blur method
You can use this post too
I am doing something like this .
int sr = 3;
for (int j = 0; j < srcimg.rows; j++) {
for (int i = 0; i < srcimg.cols; i++) {
uchar* cp_imptr = im.data;
uchar* tptr = im.data + imstep *(sr + j) + (sr + i);
int val_tptr = cp_imptr [imstep *(sr + j) + (sr + i)]; //pointer of image data amd step at 3x3
int val_cp_imptr = cp_imptr[imstep *j + i];
double s = 0;
for (int n = templeteWindowSize; n--;)
{
for (int m = templeteWindowSize; m--;)
{
uchar* t = tptr; //pointer of template
// sum
s += *t;
t++;
}
t += cstep;
}
}
cout << endl;
}

better algorithm for counting points in grids

Suppose I have a point P in [0,1]*[0,1], and [0,1] is divided into m(say 200) grids. I use A[m][m] to indicate whether [a small square centred at P with length 2h] covers each grid or not. So for a point P, A[i][j] is either (increase by) 1 or 0.
Suppose I have n such points(P1,...,Pn), I want to calculate A(for each point Pi, I redo the above procedure, adding 1 or not). How can I do this efficiently(with C++) rather than writing 3 layers of for loops to check for each grid and each point(So O(nm^2))?
I tried the naive 3 for loops with C++. It takes longer time than using some of the vectorized operations(like vector<= number for comparing n numbers together, A[bool vector, bool vector] for subsetting) in R.
Since C++ is generally faster than R, is there any smart way to implement this process?
#include <Rcpp.h>
#include <cmath>
using namespace Rcpp;
// [[Rcpp::export]]
double myfun(NumericVector u, NumericVector v)
{
double n = u.size();
double A[200][200] = {0};
double pos[200];
int i = 0, j = 0, k = 0;
for (i = 0; i < 200; i++)
{
pos[i] = (double)i / 201;
}
for (k = 0; k < n; k++)
{
for (i = 0; i < 200; i++)
{
for (j = 0; j < 200; j++)
{
if ( (fabs(u[k] - pos[i]) <= h) && (fabs(v[k] - pos[j]) <=h ) )
{
A[i][j]++;
}
}
}
}
double s = 0, avg = 0;
for (i = 0; i <200; i++)
{
for (j = 0; j < 200; j++)
{
s += A[i][j];
}
}
avg = s / (200 * 200);
return (avg);
}
The two inner loops only determine index of the point in your grid. But you can compute the index directly:
int i = (int)(u[k]*200);
int j = (int)(v[k]*200);
You probably also need to check that i and j don't reach the index 200. This only happens though, when u[k] == 1.0 or v[k] == 1.0.
double n = u.size();
double A[200][200] = {0};
for (int k = 0; k < n; k++)
{
int i = (int)(u[k]*200);
int j = (int)(v[k]*200);
if (i == 200)
i = 199;
if (j == 200)
j = 199;
A[i][j]++;
}

Putting String into a 2D Matrix in Objective C++

So I'm using Objective C++ and I want to put a string into a 4 by X (X = length of string/4) int array by using the ASCII code. The first quarter of the string (which is formatted to fit completely into a 4 by X array) is supposed to go in [0][col], the second quarter into [1][col], the third quarter into [2][col] and the fourth quarter into [3][col]. So I tried the following with 4 for loops, but it doesnt work at all, and I just can't seem to get it to work somehow. Any suggestions would be greatly appreciated.
textMatrix is the matrix in which I want to put the NSString/ASCII number, and inputFinal is the NSString itself. Length * (1/4) or whatever is also always going to be an integer.
for(int i = 0; i < length*(1/4); i++)
{
textMatrix[0][i] = (int)[inputFinal characterAtIndex: i];
}
for(int j = length*(1/4); j < length*(2/4); j++)
{
textMatrix[1][j] = (int)[inputFinal characterAtIndex: j];
}
for(int k = length*(2/4); k < length*(3/4); k++)
{
textMatrix[2][k] = (int)[inputFinal characterAtIndex: k];
}
for(int l = length*(3/4); l < length; l++)
{
textMatrix[3][l] = (int)[inputFinal characterAtIndex: l];
}
You can rewrite your 4 loops in 1 loop:
for(int i = 0; i < length; i++)
{
textMatrix[i/4][i%4] = (int)[inputFinal characterAtIndex:i];
}
I don't think I understand what you're trying to do..
Given a string: "Here";
do you want:
Matrix[0][0] = 'H';
Matrix[1][1] = 'e';
Matrix[2][2] = 'r';
Matrix[3][3] = 'e';
If so then this works:
#import <objc/objc.h>
#import <objc/Object.h>
#import <Foundation/Foundation.h>
#implementation TestObj
int main()
{
NSString* str = #"Here";
int matrix[4][4] = {0};
for (int i = 0, j = 0; j < 4; ++j)
{
matrix[i][i++] = (int) [str characterAtIndex: j];
}
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
printf("%c", (char)matrix[i][j]);
}
}
return 0;
}
#end
The above prints Here.
actually a double loop like so ended up working best for me:
int index = 0;
for(int row = 0; row < 4; row++)
{
for(int col = 0; col < length/4; col++)
{
textMatrix[row][col] = (int)[inputFinal characterAtIndex:index];
index++;
}
}