Threshold calculation without "if else"

Given following logic
T=1, if x < m1
T=2, if x >= m1 && x < m2
T=3, if x >= m2 && x < m3
T=4, if x >= m3
x is a parameter; m1, m2, m3 are thresholds to determine the conversion from x to T. Is there a way to calculate T without using "if"? Say, "rem" or "mod" or something without logic operation?

4 Comments

Really? We cannot solve this problem without the logic operation?
Star Strider
Star Strider on 10 Mar 2015
Edited: Star Strider on 10 Mar 2015
How could you possibly solve it without logic operations? That’s how you defined it!
If you believe it could be solved without logic operations, go for it ! I’ll be interested in seeing if your solution produces results equivalent to Guillaume’s or mine.
ha, solved:
m = [m1, m2, m3];
div = floor(x./m);
reg_score = div./(div+eps);
reg = [1,reg_score(1),reg_score(2),reg_score(3)];
T = sum(reg)
Guillaume
Guillaume on 11 Mar 2015
Edited: Guillaume on 11 Mar 2015
Never mind that your solution only works with scalars whereas ours work on matrices of any shape, you're using floating point division, one of the slowest operation for a processor instead of comparison, one of the fastest operation.
Kind of pointless really. Particularly, that div./(div+eps) which is just a slow and roundabout way of saying div >= 1.

Sign in to comment.

 Accepted Answer

T = 1 + (x >= m1) + (x >= m2) + (x >= m3)
would work. May not be more efficient that if though.

5 Comments

Thanks Guillaume, but your answer still uses "if" :)
Guillaume
Guillaume on 10 Mar 2015
Edited: Guillaume on 10 Mar 2015
Huh? No it doesn't, just comparisons and sums. As per your request "something pure calculation".
Logic operations are the simplest operations that a processor can do. I don't see why you'd want to avoid them. Furthermore, they're definitively part of pure calculation.
If you really want to go the roundabout and slow way, you could do:
[~, T] = histc(x, [-Inf m1 m2 m3 Inf]);
Of course under the hood histc uses logic operations.
Your problem is one of logic operations.
@Guillaume: histc is the most efficient solution.
Timing comparison:
  • With scalar:
x = rand;
m1 = 0.25; m2 = 0.5; m3 = 0.75;
%method 1: my solution
timeit(@() 1 + (x >= m1) + (x >= m2) + (x >= m3), 1)
%method 2: Star's solution
timeit(@() 1*(x < m1) + 2*((x >= m1) & (x < m2)) + 3*((x >= m2) & (x < m3)) + 4*(x >= m3), 1)
%method 3: Kyle's solution
timeit(@() sum([1 floor(x./[m1 m2 m3]) ./ (floor(x./[m1 m2 m3]) + eps)]), 1)
%method 4: histc
timeit(@() histc(x, [-Inf m1 m2 m3 Inf]), 2)
%method 5: Image's solution
timeit(@() imquantize(x, [m1 m2 m3]), 1)
Timings:
  • method 1 (mine): 6.6384955612319e-06
  • method 2 (star): 8.68228864632548e-06
  • method 3 (kyle): 9.01446251150368e-06
  • method 4 (histc): 1.3435760719302e-05
  • method 5 (image): 2.7342570776026e-05
sum of logical is fastest, histc and imquantize are ten times slower. Kyle's method is surprisingly not too bad but still slower.
  • with matrices
x = rand(2000);
m1 = 0.25; m2 = 0.5; m3 = 0.75;
%method 1: my solution
timeit(@() 1 + (x >= m1) + (x >= m2) + (x >= m3), 1)
%method 2: Star's solution
timeit(@() 1*(x < m1) + 2*((x >= m1) & (x < m2)) + 3*((x >= m2) & (x < m3)) + 4*(x >= m3), 1)
%method 3: Kyle's solution
timeit(@() sum([1 floor(x./[m1 m2 m3]) ./ (floor(x./[m1 m2 m3]) + eps)]), 1)
%method 4: histc
timeit(@() histc(x, [-Inf m1 m2 m3 Inf]), 2)
%method 5: Image's solution
timeit(@() imquantize(x, [m1 m2 m3]), 1)
  • method 1 (mine): 0.0722110642432628
  • method 2 (star): 0.173027548846752
  • method 3 (kyle): Does not work!
  • method 4 (histc): 0.0570872784882915
  • method 5 (image): 0.05592453728061645
histc and imquantize are slightly faster (probably because they only loop once over the matrix). Kyle's method does not work on matrices / vectors

Sign in to comment.

More Answers (1)

There sure is, if you have the Image Processing Toolbox . The function is called imquantize() . Here's a full demo:
% T=1, if x < m1
% T=2, if x >= m1 && x < m2
% T=3, if x >= m2 && x < m3
% T=4, if x >= m3
x = imread('cameraman.tif');
subplot(1,2,1);
imshow(x);
levels = [50, 150, 230]; % The "m" threshold levels.
classifiedImage = uint8(imquantize(x, levels));
subplot(1, 2, 2);
imshow(classifiedImage, []);
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
There is logic, but it's hidden - internal to the imquantize() function so you don't see it and you don't have to explicitly do logical operations yourself, you just call the function.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Asked:

on 10 Mar 2015

Commented:

on 11 Mar 2015

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!