Reading AND mask of 16x16 images from ICO file in Lua - image

I am creating a function that will parse and ICO/CUR and convert the data into plain pixels (specific to my API) that will then be fed to a dxCreateTexture function which will create the final image. I'm currently working on the case when the images inside the ICO file are 8bpp or less. Here's how it's currently done:
I read the color palette and store each color inside an array.
I move on to reading the XOR mask which contains the indices for every pixel color and store every pixel inside another table.
I then read the AND mask which I understand is 1bpp.
The code that I will post below works perfectly for 1bpp, 4bpp and 8bpp images with a size of 32x32, XOR & AND masks being interpreted correctly, but for images with 8x8, 16x16 or 48x48 sizes (and I suspect that there are other sizes too) only the XOR mask gets interpreted correctly. Reading the AND mask will result in misplaced transparent pixels. Please keep in mind that I'm not flipping the image yet, so this code will result in an upside-down image.
local IcoSignature = string.char(0,0,1,0);
local PngSignature = string.char(137,80,78,71,13,10,26,10);
local AlphaByte = string.char(255);
local TransparentPixel = string.char(0,0,0,0);
function ParseCur(FilePath)
if (fileExists(FilePath) == true) then
local File = fileOpen(FilePath);
if (File ~= false) and (fileRead(File,4) == IcoSignature) then
local Icons = {}
for i = 1,fileReadInteger(File,2) do -- number of icons in file
local SizeX = fileReadInteger(File,1); -- icon width
if (SizeX == 0) then
SizeX = 256;
end
local SizeY = fileReadInteger(File,1); -- icon height
if (SizeY == 0) then
SizeY = 256;
end
fileRead(File,2); -- skip ColorCount and Reserved
local PlanesNumber = fileReadInteger(File,2);
local BitsPerPixel = fileReadInteger(File,2);
local Size = fileReadInteger(File); -- bytes occupied by icon
local Offset = fileReadInteger(File); -- icon data offset
Icons[i] = {
PlanesNumber = PlanesNumber,
BitsPerPixel = BitsPerPixel,
SizeX = SizeX,
SizeY = SizeY,
Texture = true
}
local PreviousPosition = fileGetPos(File);
fileSetPos(File,Offset);
if (fileRead(File,8) == PngSignature) then -- check data format (png or bmp)
fileSetPos(File,Offset);
-- to do
else
fileSetPos(File,Offset+4); -- skip BITMAPINFOHEADER Size
local SizeX = fileReadInteger(File);
local SizeY = fileReadInteger(File)/2;
local PlanesNumber = fileReadInteger(File,2);
local BitsPerPixel = fileReadInteger(File,2);
fileRead(File,24); -- skip rest of BITMAPINFOHEADER
local Pixels = {}
if (BitsPerPixel == 1) or (BitsPerPixel == 4) or (BitsPerPixel == 8) then
local Colors = {}
for j = 1,2^(PlanesNumber*BitsPerPixel) do
Colors[j] = fileRead(File,3)..AlphaByte;
fileRead(File,1);
end
local PixelsPerByte = 8/BitsPerPixel;
local CurrentByte;
for y = 1,SizeY do -- XOR mask
Pixels[y] = {}
local CurrentRow = Pixels[y];
for x = 0,SizeX-1 do
local CurrentBit = x%PixelsPerByte;
if (CurrentBit == 0) then
CurrentByte = fileReadInteger(File,1);
end
CurrentRow[x+1] = Colors[bitExtract(
CurrentByte,
(PixelsPerByte-1-CurrentBit)*BitsPerPixel,BitsPerPixel
)+1];
end
end
for y = 1,SizeY do -- AND mask
local CurrentRow = Pixels[y];
for x = 0,SizeX-1 do
local CurrentBit = x%8;
if (CurrentBit == 0) then
CurrentByte = fileReadInteger(File,1);
end
if (bitExtract(CurrentByte,7-CurrentBit,1) == 1) then
CurrentRow[x+1] = TransparentPixel;
end
end
end
for y = 1,SizeY do -- concatenate rows into strings
Pixels[y] = table.concat(Pixels[y]);
end
Icons[i].Texture = dxCreateTexture(
table.concat(Pixels)..string.char(
bitExtract(SizeX,0,8),bitExtract(SizeX,8,8),
bitExtract(SizeY,0,8),bitExtract(SizeY,8,8)
), -- plain pixels
nil,
false
);
elseif (BitsPerPixel == 16) or (BitsPerPixel == 24) or (BitsPerPixel == 32) then
-- to do
end
end
fileSetPos(File,PreviousPosition); -- continue reading next ICO header
end
fileClose(File);
return Icons;
end
end
end
I suppose that fileExists, fileOpen, fileClose, fileGetPos and fileSetPos are self-explanatory functions. The rest of the functions' arguments are as follows:
fileRead(file file, number bytes) - reads bytes bytes from file and returns them as a string
fileReadInteger(file file, [number bytes = 4], [bool order = true]) - reads an integer with the size of bytes bytes from file in order (little -edian = true, big-edian = false)
bitExtract(number value, number filed, number width)
dxCreateTexture(string pixels, [string format = "argb"], [bool mipmaps = true])
Here are some outputs of the function in its current state: http://i.imgur.com/dRlaoan.png
The first image is 16x16 with AND mask code commented out, second is 32x32 with AND mask code commented out, third is 16x16 with AND mask code and fourth is 32x32 with AND mask code. 8x8 and 48x48 images with AND mask code look the same as the third image in the demonstration.
ICO used for demonstration: http://lua-users.org/files/wiki_insecure/lua-std.ico

Thank you, #EgorSkriptunoff!
This mask is also a subject to right-padding its every line with zeroes.
This was indeed the problem. Three lines of code inside each loop solved it.
XOR mask:
if ((SizeX/PixelsPerByte)%4 ~= 0) then
fileRead(File,4-SizeX/PixelsPerByte%4);
end
AND mask:
if ((SizeX/8)%4 ~= 0) then
fileRead(File,4-SizeX/8%4);
end

Related

I want to correct this code for images, what change need to do..?

Currently i am recognzing a face, means i have to find a face which we have to test is in training database or not..! So, i have to decide yes or no..
Yes means find image, and no means print message that NO IMAGE IN DATABASE. I have a program, Currently this program is finding a correct image correctly, but even when there is no image, even it shows other image which not matches.. Actually it should print NO IMAGE IN DATABASE.
So, How to do..?
Here is a Test and training images data on this link.
http://www.fileconvoy.com/dfl.php?id=g6e59fe8105a6e6389994740914b7b2fc99eb3e445
My Program is in terms of different four .m files, and it is here,we have to run only first code.. and remaining 3 are functions, it is also given here..**
clear all
clc
close all
TrainDatabasePath = uigetdir('D:\Program Files\MATLAB\R2006a\work', 'Select training database path' );
TestDatabasePath = uigetdir('D:\Program Files\MATLAB\R2006a\work', 'Select test database path');
prompt = {'Enter test image name (a number between 1 to 10):'};
dlg_title = 'Input of PCA-Based Face Recognition System';
num_lines= 1;
def = {'1'};
TestImage = inputdlg(prompt,dlg_title,num_lines,def);
TestImage = strcat(TestDatabasePath,'\',char(TestImage),'.jpg');
im = imread(TestImage);
T = CreateDatabase(TrainDatabasePath);
[m, A, Eigenfaces] = EigenfaceCore(T);
OutputName = Recognition(TestImage, m, A, Eigenfaces);
SelectedImage = strcat(TrainDatabasePath,'\',OutputName);
SelectedImage = imread(SelectedImage);
imshow(im)
title('Test Image');
figure,imshow(SelectedImage);
title('Equivalent Image');
str = strcat('Matched image is : ',OutputName);
disp(str)
function T = CreateDatabase(TrainDatabasePath)
TrainFiles = dir(TrainDatabasePath);
Train_Number = 0;
for i = 1:size(TrainFiles,1)
if
not(strcmp(TrainFiles(i).name,'.')|strcmp(TrainFiles(i).name,'..')|strcmp(TrainFiles(i).name,'Thu mbs.db'))
Train_Number = Train_Number + 1; % Number of all images in the training database
end
end
T = [];
for i = 1 : Train_Number
str = int2str(i);
str = strcat('\',str,'.jpg');
str = strcat(TrainDatabasePath,str);
img = imread(str);
img = rgb2gray(img);
[irow icol] = size(img);
temp = reshape(img',irow*icol,1); % Reshaping 2D images into 1D image vectors
T = [T temp]; % 'T' grows after each turn
end
function [m, A, Eigenfaces] = EigenfaceCore(T)
m = mean(T,2); % Computing the average face image m = (1/P)*sum(Tj's) (j = 1 : P)
Train_Number = size(T,2);
A = [];
for i = 1 : Train_Number
temp = double(T(:,i)) - m;
Ai = Ti - m
A = [A temp]; % Merging all centered images
end
L = A'*A; % L is the surrogate of covariance matrix C=A*A'.
[V D] = eig(L); % Diagonal elements of D are the eigenvalues for both L=A'*A and C=A*A'.
L_eig_vec = [];
for i = 1 : size(V,2)
if( D(i,i)>1 )
L_eig_vec = [L_eig_vec V(:,i)];
end
end
Eigenfaces = A * L_eig_vec; % A: centered image vectors
function OutputName = Recognition(TestImage, m, A, Eigenfaces)
ProjectedImages = [];
Train_Number = size(Eigenfaces,2);
for i = 1 : Train_Number
temp = Eigenfaces'*A(:,i); % Projection of centered images into facespace
ProjectedImages = [ProjectedImages temp];
end
InputImage = imread(TestImage);
temp = InputImage(:,:,1);
[irow icol] = size(temp);
InImage = reshape(temp',irow*icol,1);
Difference = double(InImage)-m; % Centered test image
ProjectedTestImage = Eigenfaces'*Difference; % Test image feature vector
Euc_dist = [];
for i = 1 : Train_Number
q = ProjectedImages(:,i);
temp = ( norm( ProjectedTestImage - q ) )^2;
Euc_dist = [Euc_dist temp];
end
[Euc_dist_min , Recognized_index] = min(Euc_dist);
OutputName = strcat(int2str(Recognized_index),'.jpg');
So, how to generate error massege when no image matches..?
At the moment, your application appears to find the most similar image (you appear to be using Euclidean distance as you measure of similarity), and return it. There doesn't seem to be any concept of whether the image "matches" or not.
Define a threshold on similarity, and then determine whether your most similar image meets that threshold. If it does, return it, otherwise display an error message.

Image manipulation with Matlab - intensity and tif image

I have to analyse a set of images, and these are the operations I need to perform:
sum another set of images (called open beam in the code), calculate the median and rotate it by 90 degrees;
load a set of images, listed in the file "list.txt";
the images have been collected in groups of 3. For each group, I want to produce an image whose intensity values are 3 times the image median above a certain threshold and otherwise equal to the sum of the intensity values;
for each group of three images, subtract the open beam median (calculated in 1.) from the combined image (calculated in 3.)
Considering one of the tifs produced using the process above, I have that the maximum value is 65211, which is not 3* the median for the three images of the corresponding group (I checked considering the pixel position). Do you have any suggestion on why this happens, and how I could fix it?
The code is reported below. Thanks!
%Here we calculate the average for the open beam
clear;
j = 0;
for i=1:5
s = sprintf('/Users/Alberto/Desktop/Midi/17_OB_2.75/midi_%04i.fits',i);
j = j+1;
A(j,:,:) = uint16(fitsread(s));
end
OB_median = median(A,1);
OB_median = squeeze(OB_median);
OB_median_rot=rot90(OB_median);
%Here we calculate, for each projection, the average value from the three datasets
%Read list of images from text file
fid = fopen('/Users/Alberto/Desktop/Midi/list.txt', 'r');
a = textscan(fid, '%s');
fclose(fid);
%load images
j = 0;
for i = 1:1:42 %556 entries; 543 valid values
s = sprintf('/Users/Alberto/Desktop/Midi/%s',a{1,1}{i,1});
j = j+1;
A(j,:,:) = uint16(fitsread(s));
end
threshold = 80 %This is a discretional number. I put it after noticing
%that we get the same number of pixels with a value >100 if we use 80 or 50.
k = 0;
for ii = 1:3:42
N(1,:,:) = A(ii,:,:);
N(2,:,:) = A(ii+1,:,:);
N(3,:,:) = A(ii+2,:,:);
median_N = median(N,1);
median_N = squeeze(median_N);
B(:,:) = zeros(2160,2592);
for i = 1:1:2160
for j = 1:1:2592
RMS(i,j) = sqrt((double(N(1,i,j).^2) + double(N(2,i,j).^2) + double(N(3,i,j).^2))/3);
if RMS(i,j) > threshold
%B(i,j) = 30;
B(i,j) = 3*median_N(i,j);
else
B(i,j) = A(ii,i,j) + A(ii+1,i,j) + A(ii+2,i,j);
%B(i,j) = A(ii,i,j);
end
end
end
k = k+1;
filename = sprintf('/Users/Alberto/Desktop/Midi/Edited_images/Despeckled_images/despeckled_image_%03i.tif',k);
%Now we rotate the matrix
B_rot=rot90(B);
imwrite(B_rot, filename);
%imwrite(uint16(B_rot), filename);
%Now we subtract the OB median
B_final_rot = double(B_rot) - 3*double(OB_median_rot);
filename = sprintf('/Users/Alberto/Desktop/Midi/Edited_images/Final_image/final_image_%03i.tif',k);
imwrite(uint16(B_final_rot), filename);
end
The maximum integer that can be represented by the uint16 data type is
>> a=100000; uint16(a)
ans =
65535
To circumvent this limitation you need to rescale your data as type double and adjust the range (the image contrast) to agree with the limits imposed by the uint16 data type, before saving as uint16.

Speed up deinterleave and concatenation for TIFF

I work in a neuro-lab that records pictures of mouse brains. The raw files that the cameras record to record pictures from alternating cameras (picture of brain, picture of mouse head, picture of brain, etc) We're converting these files to TIFF, deinterleaving them, and then concatenating the files.
The concatenation is far too slow to be of any use. I'm not yet learned enough in Matlab to be able to troubleshoot. How can we improve the speed of this code?
%convert micam raw to tiff using image j
javaaddpath 'C:\Program Files\MATLAB\R2013a\java\mij.jar';
javaaddpath 'C:\Program Files\MATLAB\R2013a\java\ij.jar';
MIJ.start('C:\users\lee\desktop\imagej');
MIJ.run('Install...', 'install=[C:\\Users\\lee\\Desktop\\ImageJ\\macros\\Matthias\\Helmchen Macros modified djm.ijm]');
MIJ.run('Run...', 'path=[C:\\Users\\lee\\Desktop\\ImageJ\\macros\\Matthias\\Helmchen Macros modified djm.ijm]');
MIJ.run('Convert MiCam Raw to TIFF');
pause (30); %to prevent race condition, needs to be fixed to wait for input
MIJ.exit;
%prepare tiff stack folder fast
myFolder = uigetdir;
cd(myFolder);
filePattern = fullfile(myFolder, '*.tif');
tifffiles = dir(filePattern);
count = length(tifffiles);
for z = 1:count
A = tifffiles.name;
I = imreadtiffstack (A, 256);
%crop tiff stack
sizecrop = size(I);
framenum = sizecrop(3);
cropcollector = ones([100 101 256] , 'uint16'); %preallocates matrix for depositing cropped frames
for k = 1:framenum
frame = I(:,:,k);
I2 = imcrop(frame,[20 0 100 100]);
cropcollector(:,:,k)=I2;
%deinterleaves tiff stack
sizedinlv = size(cropcollector);
framenumdinlv = sizedinlv(3);
oddcollector = ones([100 101 128], 'uint16'); %preallocates array for odd deinterleaved frames
evencollector = ones([100 101 128], 'uint16'); %preallocates array for even deinterleaved frames
countodd = 0;
counteven = 0;
for k2 = (1:framenumdinlv)
if mod(k2, 2)==1
framedinlv = cropcollector(:,:,k2);
countodd = countodd +1;
oddcollector(:,:,countodd)=framedinlv;
else
framedinlv = cropcollector(:,:,k2);
counteven = counteven + 1;
evencollector(:,:,counteven)=framedinlv;
%concatenate
if mod (z, 2)==1;
oddhold = ones([100 101 128], 'uint16');
evenhold = ones([100 101 128], 'uint16');
oddhold = repmat(oddcollector, 1);
evenhold = repmat(evencollector, 1);
else
odd = num2str(1);
even = num2str(2);
brain = ones([100 101 256], 'uint16');
mouse = ones([100 101 256], 'uint16');
% nameoddframes = strcat(A(1:10), odd);
%nameevenframes = strcat(A(1:10), even);
brain = cat(3, oddhold, oddcollector);
mouse = cat(3, evenhold, evencollector);
end
end
end
end
end
%background subtraction

Lua, Odd behavior with bitmap reading

In a bitmap reader I found and modified, the first few colors of some images are innacurate by a large amount, in other images it reads perfectly, in just now, the first 7 or so colors of an image that I must have it read are not accurate at all. I don't understand byte orders, so please help!
Heres my modified copy of the code:
---
-- (Evil Steve)Because I'm a kind and wonderful person: http://www.gamedev.net/topic/572784-lua-read-bitmap/
---
function error(err)
-- Replace with your own error output method:
print(err);
end
-- Helper function: Parse a 16-bit WORD from the binary string
function ReadWORD(str, offset)
local loByte = str:byte(offset);
local hiByte = str:byte(offset+1);
return hiByte*256 + loByte;
end
-- Helper function: Parse a 32-bit DWORD from the binary string
function ReadDWORD(str, offset)
local loWord = ReadWORD(str, offset);
local hiWord = ReadWORD(str, offset+2);
return hiWord*65536 + loWord;
end
-- Process a bitmap file in a string, and call DrawPoint for each pixel
function OpenBitmap(File, Stream)
if Stream == nil then Stream = false end
local bytecode = File:read("*a")
-------------------------
-- Parse BITMAPFILEHEADER
-------------------------
local offset = 1;
local bfType = ReadWORD(bytecode, offset);
if(bfType ~= 0x4D42) then
error("Not a bitmap file (Invalid BMP magic value)");
return;
end
local bfOffBits = ReadWORD(bytecode, offset+10);
-------------------------
-- Parse BITMAPINFOHEADER
-------------------------
offset = 15; -- BITMAPFILEHEADER is 14 bytes long
local biWidth = ReadDWORD(bytecode, offset+4);
local biHeight = ReadDWORD(bytecode, offset+8);
local biBitCount = ReadWORD(bytecode, offset+14);
local biCompression = ReadDWORD(bytecode, offset+16);
if(biBitCount ~= 24) then
error("Only 24-bit bitmaps supported (Is " .. biBitCount .. "bpp)");
return;
end
if(biCompression ~= 0) then
error("Only uncompressed bitmaps supported (Compression type is " .. biCompression .. ")");
return;
end
---------------------
-- Parse bitmap image
---------------------
local TmpImg = {}
if Stream == false then
for y = biHeight-1, 0, -1 do
offset = bfOffBits + (biWidth*biBitCount/8)*y + 1;
for x = 0, biWidth-1 do
local b = bytecode:byte(offset);
local g = bytecode:byte(offset+1);
local r = bytecode:byte(offset+2);
offset = offset + 3;
TmpImg[#TmpImg+1] = {r,g,b}
end
end
else
for y = biHeight-1, 0, -1 do
offset = bfOffBits + (biWidth*biBitCount/8)*y + 1;
for x = 0, biWidth-1 do
local b = bytecode:byte(offset);
local g = bytecode:byte(offset+1);
local r = bytecode:byte(offset+2);
offset = offset + 3;
TmpImg[#TmpImg+1] = r
TmpImg[#TmpImg+1] = g
TmpImg[#TmpImg+1] = b
end
end
end
return TmpImg, biWidth, biHeight
end
function OpenBmp(FileName, Stream)
if Stream == nil then Stream = false end
if FileName == nil then
return false
end
local File = assert(io.open(FileName, 'rb'))
local Data, Width, Height = OpenBitmap(File, Stream)
File:close()
return Data, Width, Height
end
I cannot give you the code I run with this, sadly, because it has too many dependencies to bother with, but its output is:
<254, 254, 254, 256>
<99, 254, 254, 256>
<49, 74, 91, 256>
When ran with the following bmp colors:
<90, 106, 113, 256>
<188, 194, 197, 256>
<254, 254, 254, 256>
I don't see any pattern, and the bmp reader seems to make sense, it prints no errors when reading, and I made sure to save the bmp as 24 bit as required. all help appreciated :-)
In the example above, offset wasn't considering that row widths must always be a multiple of 4 bytes wide, with it padded if it was below the multiple of 4. You can resolve this by rounding up row width to the nearest multiple of 4, which explains why the function sometimes read images accurately, and other times not.
the behavior from the pixels in the beginning being false, but the rest later on being accurate was due to creeping, logically, the first would be accurate, with the last inaccurate, but the creeping went the opposite way due to bitmaps being read bottom-up and right-left.

Matlab SVM for Image Classification

I am using SVM function of Matlab to classify images that are read from a folder. What I want to do is first read 20 images from the folder, then use these to train the SVM, and then give a new image as input to decide whether this input image falls into the same category of these 20 training images or not. If it is, then the classification result should give me 1, if not, then I expect to receive -1.
Up to now, my written code is as follows:
imagefiles = dir('*.jpg');
nfiles = 20;
for i = 1:nfiles
currentfilename = imagefiles(i).name;
currentimage = imread(currentfilename);
images{i} = currentimage;
images{i} = im2double(images{i});
images{i} = rgb2gray(images{i});
images{i} = imresize(images{i},[200 200]);
images{i} = reshape(images{i}', 1, size(images{i},1)*size(images{i},2));
end
trainData = zeros(nfiles, 40000);
for ii=1:nfiles
trainData(ii,:) = images{ii};
end
class = [1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 1 1 1 1 1 1];
SVMStruct = svmtrain (trainData, class);
inputImg = imread('testImg.jpg');
inputImg = im2double(inputImg);
inputImg = rgb2gray(inputImg);
inputImg = imresize(inputImg, [200 200]);
inputImg = reshape (inputImg', 1, size(inputImg,1)*size(inputImg,2));
result = svmclassify(SVMStruct, inputImg);
Since the images are read by series from the folder, so camethe cell images. Then I converted them to grayscale as shown in the code, and resized them, since those images were NOT of same size. Thus after this step, I had 20 images, all of each with size 200x200. And at last, I gave these to serve as my training dataset, with 20 rows, and 200x200 columns. I checked all of these size results, and they seemed to work fine. But right now the only problem is, no matter what kind of input image I give it to predict, it always gives me a result as 1, even for those very different images. Seems like it is not working correctly. Could someone help me check out where should be the problem here? I couldn't find any explanation from the existing sources on the internet. Thanks in advance.
Here is a function to read all images that may help you
function X = ReadImgs(Folder,ImgType)
Imgs = dir(fullfile(Folder, ImgType));
NumImgs = size(Imgs,1);
image = double(imread(fullfile(Folder, Imgs(1).name)));
X = zeros([NumImgs size(image)]);
for i=1:NumImgs,
img = double(imread(fullfile(Folder, Imgs(i).name)));
if (size(image,3) == 1)
X(i,:,:) = img;
else
X(i,:,:,:) = img;
end
end
Source: http://computervisionblog.wordpress.com/2011/04/13/matlab-read-all-images-from-a-folder-everything-starts-here/
this is should be works in MATLAB
clear all;
clc;
folder = 'gambar 1';
dirImage = dir( folder );
numData = size(dirImage,1);
M ={} ;
% read image
for i=1:numData
nama = dirImage(i).name;
if regexp(nama, '(lion|tiger)-[0-9]{1,2}.jpg')
B = cell(1,2);
if regexp(nama, 'lion-[0-9]{1,2}.jpg')
B{1,1} = double(imread([folder, '/', nama]));
B{1,2} = 1;
elseif regexp(nama, 'tiger-[0-9]{1,2}.jpg')
B{1,1} = double(imread([folder, '/', nama]));
B{1,2} = -1;
end
M = cat(1,M,B);
end
end
% convert image holder from cell to array
numDataTrain = size(M,1);
class = zeros(numDataTrain,1);
arrayImage = zeros(numDataTrain, 300 * 300);
for i=1:numDataTrain
im = M{i,1} ;
im = rgb2gray(im);
im = imresize(im, [300 300]);
im = reshape(im', 1, 300*300);
arrayImage(i,:) = im;
class(i) = M{i,2};
end
SVMStruct = svmtrain(arrayImage, class);
% test for lion
lionTest = double(imread('gambar 1/lion-test.jpg' ));
lionTest = rgb2gray(lionTest);
lionTest = imresize(lionTest, [300 300]);
lionTest = reshape(lionTest',1, 300*300);
result = svmclassify(SVMStruct, lionTest);
result
https://github.com/gunungloli666/svm-test

Resources