Porting codes from MATLAB to C(OpenCV) - c

I've been working on trying to port a small meanshift tracking program, which is sort of different from the meanshift that involves performing back-projection, from MATLAB to C, but I'm having some problems with it.
I don't know how to interpret some of the lines from MATLAB to C(OpenCV).
https://drive.google.com/drive/folders/0B2r9FmkcbNwAbHdtVEVkSW1SQW8
I put the 2 .m files, 1 .cpp file and a directory where pictures are placed for both programs to use on my googledrive.
"demo_MultiMeanShift_1st_ver_0413.m" is what I'd like to port to C,
"boxfilter.m" is the function that's found in the following website:
http://blog.csdn.net/wds555/article/details/23176313
(It's a Chinese website however)
and "Meanshift_demo.cpp" is what I've done so far.
There're mainly two parts that I don't know how to interpret from MATLAB to C:
1st part:
bas = zeros(hei,wid,N) ;
for i = 1 : 1 : N
bas(:,:,i) = boxfilter( ones(hei,wid), floor(r/i) ) ;
end
Ic_mean = zeros(hei,wid,dep,N) ;
for i = 1 : 1 : N
for d = 1 : 1 : dep
%Average pixel value(s) of the object being tracked
Ic_mean(pc(2)-(r+sw) : pc(2)+(r+sw), pc(1)-(r+sw) : pc(1)+(r+sw), d, i) = boxfilter(Ip(pc(2)-(r+sw) : pc(2)+(r+sw), pc(1)-(r+sw) : pc(1)+(r+sw),d), floor(r/i)) ./ bas(pc(2)-(r+sw) : pc(2)+(r+sw), pc(1)-(r+sw) : pc(1)+(r+sw),i);
%Ic_mean(:,:,d,i) = boxfilter(Ip(:,:,d), floor(r/i)) ./ bas(:,:,i);
end
end
dis = zeros(1,N) ;
2nd part:
for i = -sw + pc(2) : 2 : sw + pc(2)
for j = -sw + pc(1) : 2 : sw + pc(1)
for d = 1 : 1 : N
dis(d) = sqrt( ... % (p1(R1, G1, B1) - p2(R2, G2, B2))^2
( Ic_mean(i,j,1,d) - Ip_mean(pc(2),pc(1),1,d) )^2 ...
+ ( Ic_mean(i,j,2,d) - Ip_mean(pc(2),pc(1),2,d) )^2 ...
+ ( Ic_mean(i,j,3,d) - Ip_mean(pc(2),pc(1),3,d) )^2 );
end
if disMin > mean(dis)
disMin = mean(dis) ;
i_hold = i ;
j_hold = j ;
end
end
end
In MATLAB I can read, access and change pixel values directly, such as:
Img(x,y) = 0 to set some pixel value to be 0
or
Img(:,:,1) = 1 to set the pixels of certain channel to all be 0.
Can I also do those things as rapidly as what's shown above is in OpenCV?

In MATLAB I can read, access and change pixel values directly, such
as:
Img(x,y) = 0 to set some pixel value to be 0 or Img(:,:,1) = 1 to set
the pixels of certain channel to all be 0.
Can I also do those things as rapidly as what's shown above is in
OpenCV?
Of course this is possible. To set value of single pixel use:
img.at<img_single_element_type>(y,x) = 0;
where img_single_element_type depends on mat type and might be double, unsigned char, int, etc... See documentation for more information.
To set values in whole image (or part of image) use setTo method.
I don't know much about Matlab, so i can't help you with porting this code, but look at this and this project. It's similar project (object tracker - Open TLD(Tracking Learning Detection) aka Predator) written in Matlab(first link) and ported to C++(second link). Hope it helps.

Related

How to add additional zero arrrays

I have the following problem in my simulation.
A is an array 24 x 2. I am going to split it and get 4 or 12 array. It means that I group 6 or 2 array. It will be ok, if I use even "split" coefficient. If it is odd, I can"t split A.[ I can't group 5 or 7, because of 24/5=4*5 + 4 ( or 5*5 -1) or 24/7=7*3+3.
That's why I going to do the following:
If I have 24 x 2 and need group every 5 together:
block 1 : A(1,:), A(2,:),A(3,:),A(4,:),A(5,:)
block 2 : A(6,:), A(7,:),A(8,:),A(9,:),A(10,:)
block 3 : A(11,:), A(12,:),A(13,:),A(14,:),A(15,:)
block 4 : A(16,:), A(17,:),A(18,:),A(19,:),A(20,:)
block 5 : A(21,:), A(22,:),A(23,:),A(24,:), ?
As you can see the 5th block is not full, Matlab gives me an error. My idea is to create A(25,:)=0. For my simulation it will be ok.
I am going to simulate it as function:
A=rand(m,n)
w- # number of a vector that i would like group together ( in ex., it is `5`)
if mod(w,2)==0
if mod(m,2)==0
% do....
else
% remainder = 0
end
else
if mod(m,2)==0
% remainder = 0
else
%do...
end
I was going to simulate like above, but then I have noticed that it doesn't work. Because 24/10 = 2*10+4. So I should write something else
I can find the reminder as r = rem(24,5). As an example above, MatLab gives me r=4. then I can find a difference c= w-r =1 and after that, I don't know how to do that.
Could you suggest to me how to simulate such a calculation?
Determine the number of blocks needed, calculate the virtual amount of rows needed to fill these blocks, and add as many zero rows to A as the difference between the virtual and actual amount of rows. Since you didn't mention, what the actual output should look like (array, cell array, ...), I chose a reshaped array.
Here's the code:
m = 24;
n = 2;
w = 5;
A = rand(m, n)
% Determine number of blocks
n_blocks = ceil(m / w);
% Add zero rows to A
A(m+1:w*n_blocks, :) = 0
% Reshape A into desired format
A = reshape(A.', size(A, 1) / n_blocks * n, n_blocks).'
The output (shortened):
A =
0.9164959 0.1373036
0.5588065 0.1303052
0.4913387 0.6540321
0.5711623 0.1937039
0.7231415 0.8142444
0.9348675 0.8623844
[...]
0.8372621 0.4571067
0.5531564 0.9138423
A =
0.91650 0.13730
0.55881 0.13031
0.49134 0.65403
0.57116 0.19370
0.72314 0.81424
0.93487 0.86238
[...]
0.83726 0.45711
0.55316 0.91384
0.00000 0.00000
A =
0.91650 0.13730 0.55881 0.13031 0.49134 0.65403 0.57116 0.19370 0.72314 0.81424
0.93487 0.86238 0.61128 0.15006 0.43861 0.07667 0.94387 0.85875 0.43247 0.03105
0.48887 0.67998 0.42381 0.77707 0.93337 0.96875 0.88552 0.43617 0.06198 0.80826
0.08087 0.48928 0.46514 0.69252 0.84122 0.77548 0.90480 0.16924 0.82599 0.82780
0.49048 0.00514 0.99615 0.42366 0.83726 0.45711 0.55316 0.91384 0.00000 0.00000
Hope that helps!

How to do SUM on array from outside file?

I'm newbie college student for programming studies,
so recently i have task to calculate matrix from outside files for Gauss Jordan Numeric Method, in the txt file i provide has 10 (x) and (y) data, and declare with do functions to calculate the 10 data from the txt file each for x^2, x^3, x^4, xy, x^2y
my question is : how to SUM (calculate total) each x^2, x^3 ... that was calculated by program ? i try do sum file in below and still got errors (the first argument of sum must not a scalar.)
the Fortran apps i use was Plato cc from Silverfrost.
I apologize if my english bad and my pogram looks funny.
i have 10 data in my txt looks like these :
(x) (y)
12 10
5 6
28 8
9 11
20 17
6 24
32 9
2 7
1 30
26 22
in program below i open these files and want each x and y i provide read and calculate to get x^2, x^3, x^4, xy, x^2y
Program Gauss_Jordan
Real x(10),y(10),xj,yj,xj2,xj3,xj4,xjyj,xj2yj
Open (10, file='Data.txt')
Do j = 1,10
Read(10,*) x(j), y(j)
xj2 = x(j)**2
xj3 = x(j)**3
xj4 = x(j)**4
xjyj = x(j)*y(j)
xj2yj = (x(j)**2)*y(j)
Do k = 1,10
T(xj2) = SUM( xj2, dim=1)
T(xj3) = SUM (xj3, dim=1)
T(xj4) = SUM (xj4, dim=1)
T(xjyj) = SUM (xjyj, dim=1)
T(xj2yj) = SUM (xj2yj, dim=1)
End Do
End Do
Close(10)
End
for T(xj2) I want to get one result scalar result from SUM the all xj^2 that program has been calculated.
Like in excel was expected :
(A) is 1st xj^2 value that has been calculated
.
.
.
until (J) is 10th xj^2 value that has been calculated
sxj^2 = SUM(Xj^2)
SUM (A-J)
The 'sum' intrinsic needs an array argument, which we can compute from the input arrays without using a loop, so your program could be:
Program Gauss_Jordan
Real x(10), y(10), x2(10), x3(10), x4(10), xy(10), x2y(10)
Open(10, file='Data.txt')
Do j = 1, 10
Read (10, *) x(j), y(j)
End Do
Close(10)
x2 = x**2
x3 = x**3
x4 = x**4
xy = x*y
x2y = (x**2)*y
sx2 = SUM(x2)
sx3 = SUM(x3)
sx4 = SUM(x4)
sxy = SUM(xy)
sx2y = SUM(x2y)
End
From what I see I think you are misunderstanding what the SUM intrinsic does. Since your example isn't storing xj2, xj3 etc. in arrays, SUM isn't going to be useful to you. Instead you could declare totals as scalars (as you described you wanted) and simply add the individual xj2 variables in a loop as in the example below.
Also, you should get in the habit of using the implicit none declaration. It will save you from unexpected errors due to spelling mistakes.
Program Gauss_Jordan
implicit none
Real x(10),y(10),xj,yj,xj2,xj3,xj4,xjyj,xj2yj
real :: Txj2,Txj3,Txj4,Txjyj,Txj2yj
integer :: j
Txj2 = 0
Txj3 = 0
Txj4 = 0
Txjyj= 0
Txj2yj= 0
Open (10, file='Data.txt')
Do j = 1,10
Read(10,*) x(j), y(j)
xj2 = x(j)**2
xj3 = x(j)**3
xj4 = x(j)**4
xjyj = x(j)*y(j)
xj2yj = (x(j)**2)*y(j)
Txj2 = Txj2 + xj2
Txj3 = Txj3 + xj3
Txj4 = Txj4 + xj4
Txjyj = Txjyj + xjyj
Txj2yj = Txj2yj + xj2yj
End Do
print *, 'Txj2 = ', Txj2
Close(10)
End
When I ran this I got the output below which is what I believe you intended:
3175

Convert Cell to an Array

i have a cell array with dimensions 1x16384 consists of 16384 numbers.
I tried using cell2mat(), but i get one element with all those numbers in it.
How do i convert it to an array with 1x16384 dimension.
Assuming B= cell2mat(A);
A looks like;
Columns 16382 through 16384
'15.849' '16.337' '14.872'
where as B looks like;
B =
-8.921-8.433-2.5745.23911.58714.02811.5876.7041.821-1.109-2.085-1.5970.3562.
console ;
class(A), class(A{1}), size(A), size(A{1})
ans =
cell
ans =
char
ans =
1 16384
ans =
1 6
For mcve,
Csv input file
DELIMITER = ' ';
HEADERLINES = 3;
% Import the file
newData1 = importdata('C:\Python34\co2a0000364.csv', DELIMITER, HEADERLINES);
% Create new variables in the base workspace from those fields.
vars = fieldnames(newData1);
for i = 1:length(vars)
assignin('base', vars{i}, newData1.(vars{i}));
end
new = textdata(6:16452,4);
A = new;
for z = 1:63
A(i*257)=[];
end
B = A'
A= B;
A= cell2mat(B)
B= A
You way of importing data is quite clumsy. I invite you to read the textscan function documentation, which allows much more flexibility in importing mixed data type (text and numeric data).
I propose you another way of importing, which uses textscan:
%% // Import only the 4th column of data
fid = fopen('co2a0000364.csv') ;
M = textscan( fid , '%*s%*s%*s%f' , 'Delimiter',' ' , 'HeaderLines',4) ;
fclose(fid) ;
M = cell2mat(M) ;
%% // reshape to have each channel in its own colum
M = reshape( M , 257 , [] ) ;
%% // Delete the channel number from the data table
M(1,:) = [] ;
This will give you a nice 256*64 matrix, containing the data for each of the 64 channels in one column.
if you really want them all in sequence in one column, just add:
M = M(:) ;
to the end of the code.
Explanation note: the textscan format specifier I use: '%*s%*s%*s%f' tells the function to read 4 elements per line:
- 3x strings : %s
- 1x floating point number: %f
adding the character * in the format specifier (for example %*s) for an element tells the function to ignore the element, so it does not put it into the output.

Writing values in certain positions in an array

so I have this array:
ab = 3
cd = 4
array = zeros(ab, cd);
which gives us an array looking like:
0 0 0 0
0 0 0 0
0 0 0 0
now I'd like to fill each line with certain values. I have two classes with two properties I substract from each other.
so the first entry in the first line should be computed by:
xxx = class1{1}.property - class2{1}.property
the second entry in the first line should be filled by:
xxx = class1{1}.property - class2{2}.property
third entry:
xxx = class1{1}.property - class2{3}.property
the first entry in the second line should be computed by:
xxx = class1{2}.property - class2{1}.property
I tried:
for cc = 1:ab
for hh = 1:cd
array(cc, hh) = class1{cc}.property - class2{hh}.property
end
end
However, matlab keeps telling me:"Subscripted assignment dimension mismatch."
I do understand what the problem means but I don't know how address it :/
edit:
the array should look like:
(class1{1}.property - class2{1}.property) (class1{1}.property - class2{2}.property)
(class1{2}.property - class2{1}.property) (class1{2}.property - class 2{2}.property)
As was said in comments, it's hard to know without more knowledge of the code, but it could be occurring because one or more of your class properties have more than one value. You could try something like the following to catch if the class properties are larger than 1 value.
for cc = 1:ab
for hh = 1:cd
temp = class1{cc}.property - class2{hh}.property;
if length(temp) > 1
keyboard
end
array(cc, hh) = temp;
end
end
The dimension mismatch error was due to me adding vectors (class1.property aswell as class2.property were vectors!)to each array entry.

How do I make this specific code run faster in Matlab?

I have an array with a set of chronological serial numbers and another source array with random serial numbers associated with a numeric value. The code creates a new cell array in MATLAB with the perfectly chronological serial numbers in one column and in the next column it inserts the associated numeric value if the serial numbers match in both original source arrays. If they don't the code simply copies the previous associated value until there is a new match.
j = 1;
A = {random{1:end,1}};
B = cell2mat(A);
value = random{1,2};
data = cell(length(serial), 1);
data(:,1) = serial(:,1);
h = waitbar(0,'Please Wait...');
steps = length(serial);
for k = 1:length(serial)
[row1, col1, vec1] = find(B == serial{k,1});
tf1 = isempty(vec1);
if (tf1 == 0)
prices = random{col1,2};
data(j,2) = num2cell(value);
j = j + 1;
else
data(j,2) = num2cell(value);
j = j + 1;
end
waitbar(k/steps,h,['Please Wait... ' num2str(k/steps*100) ' %'])
end
close(h);
Right now, the run-time for the code is approximately 4 hours. I would like to make this code run faster. Please suggest any methods to do so.
UPDATE
source input (serial)
1
2
3
4
5
6
7
source input (random)
1 100
2 105
4 106
7 107
desired output (data)
SR No Value
1 100
2 105
3 105
4 106
5 106
6 106
7 107
Firstly, run the MATLAB profiler (see 'doc profile') and see where the bulk of the execution time is occuring.
Secondly, don't update the waitbar on every iteration> Particularly if serial contains a large (> 100) number of elements.
Do something like:
if (mod(k, 100)==0) % update on every 100th iteration
waitbar(k/steps,h,['Please Wait... ' num2str(k/steps*100) ' %'])
end
Some points:
Firstly it would help a lot if you gave us some sample input and output data.
Why do you initialize data as one column and then fill it's second in the loop? Rather initialize it as 2 columns upfront: data = cell(length(serial), 2);
Is j ever different from k, they look identical to me and you could just drop both the j = j + 1 lines.
tf1 = isempty(vec1); if (tf1 == 0)... is the same as the single line: if (!isempty(vec1)) or even better if(isempty(vec1)) and then swap the code from your else and your if.
But I think you can probably find a fast vecotrized solution if you provide some (short) sample input and output data.

Resources