Более быстрая версия функции dec2bin для преобразования многих элементов?
Я читаю файл растрового изображения и преобразовываю каждое из значений RGB в диапазоне от 0 до 255 в двоичный файл.
Таким образом, растровое изображение 240 на 320 будет иметь 230400 значений RGB для преобразования. Первоначальная функция dec2bin была слишком медленной, поэтому я написал свою собственную, поскольку знаю, что мое значение всегда будет в диапазоне от 0 до 255.
Но прохождение значений 230400 все равно займет ок. 6 секунд на моей машине, и одноцветное растровое изображение займет около 2,3 секунды.
Есть ли способ ускорить процесс до 1 секунды или даже лучше 0,5 секунды, поскольку каждая мс считается для моего приложения?
Вот мой код:
function s = dec2bin_2(input)
if input == 255
s = [1;1;1;1;1;1;1;1];
return;
end
s = [0;0;0;0;0;0;0;0];
if input == 0
return;
end
if input >= 128
input = input - 128;
s(1) = 1;
if input == 0
return;
end
end
if input >= 64
input = input - 64;
s(2) = 1;
if input == 0
return;
end
end
if input >= 32
input = input - 32;
s(3) = 1;
if input == 0
return;
end
end
if input >= 16
input = input - 16;
s(4) = 1;
if input == 0
return;
end
end
if input >= 8
input = input - 8;
s(5) = 1;
if input == 0
return;
end
end
if input >= 4
input = input - 4;
s(6) = 1;
if input == 0
return;
end
end
if input >= 2
input = input - 2;
s(7) = 1;
if input == 0
return;
else
s(8) = 1;
end
end
end
Я думал, что если я не смогу сделать это в MATLAB, то, возможно, я сделаю преобразование в C++. Это желательно?
Благодарю.
4 ответа
Еще более быстрый способ - использовать справочные таблицы. Поскольку вы знаете, что все значения являются интенсивностями от 0 до 255, вы создаете двоичный эквивалент каждого из них, чтобы ускорить процесс.
% build table (computed once) [using gnovice option#1]
lookupTable = cell2mat(arrayfun(@(i)bitget([0:255]',9-i),1:8,'UniformOutput',0));
% random' image
I = randi(256, [240 320])-1;
% decimal to binary conversion
binI = lookupTable(I(:)+1,:);
На моей машине это заняло в среднем 0.0036329 секунд (только преобразование). Обратите внимание, что в таблице поиска почти нет места:
>> whos lookupTable
Name Size Bytes Class Attributes
lookupTable 256x8 2048 uint8
Вариант № 1: зацикливание на каждом пикселе и использование BITGET
Вы можете зациклить каждый пиксель (или значение RGB) на своем изображении и использовать BITGET, чтобы получить вектор нулей и единиц. Вот пример того, как использовать BITGET:
>> bitget(uint8(127),8:-1:1) % Get bits 8 through 1 for a uint8 value
ans =
0 1 1 1 1 1 1 1
Вариант № 2: Векторизованное решение с BITGET
Можно создать векторизованное решение, в котором вы перебираете каждый бит вместо каждого пикселя, выполняя операцию BITGET для всей матрицы изображения каждый раз в цикле. Ниже приведена одна из таких реализаций:
function B = get_bits(A,N)
% Gets the N lowest bits from each element of A
B = zeros([size(A) 0]);
nDims = ndims(A)+1;
for iBit = N:-1:1
B = cat(nDims,B,bitget(A,iBit));
end
end
Если матрица A
это 2-D (n-by-m) или 3-D (n-by-m-by-p), матрица B
будет на одно измерение больше. Дополнительное измерение будет иметь размер N
с наибольшим битом в индексе 1. Вы можете либо индексировать в этом измерении, чтобы получить значение бита, либо изменить форму B
в более легко визуализируемой форме. Вот пример использования:
>> A = uint8([126 128; 127 129]); % A 2-by-2 matrix of uint8 values
>> B = get_bits(A,8); % B is a 2-by-2-by-8 matrix
>> B(:,:,1) % Get bit 8 for each value in A
ans =
0 1
0 1
>> reshape(B,4,8) % Reshape B into a 4-by-8 matrix
ans =
0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 1
Разве вы не можете использовать bitand, чтобы получить биты напрямую?
s(0) = 256 bitand input
s(1) = 128 bitand input
s(2) = 64 bitand input
так далее...
Проблема такого рода (выполнение операции для каждого элемента в большом массиве, поскольку встроенный код Matlab слишком медленный) иногда требует решения в Java, поскольку Matlab работает на JRE, а преобразование / передача аргументов массива обычно довольно быстрая операция.
Решение gnovice звучит так, как будто оно работает для вас, но если вы столкнулись с ситуацией, которую вы не можете решить в чистом Matlab, и вы владеете Java, подумайте о написании собственного файла JAR. Это довольно легко. (ну, намного проще, чем пытаться связать C++ с Matlab!)