-
Notifications
You must be signed in to change notification settings - Fork 2
/
tag_getTvChannelClass.m
158 lines (138 loc) · 6.02 KB
/
tag_getTvChannelClass.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
function [ tvChannelClass, ocrRegion ] = tag_getTvChannelClass( videoURI )
%TAG_GETTVCHANNELCLASS Returns TV Channel class for given video
% Detailed explanation goes here
%% Load dbConfig
load(db_getDbConfigFileURI(), 'indexClassIntType');
%% Set initial output vars
tvChannelClass = 0;
tvChannelClass = cast(tvChannelClass, indexClassIntType);
ocrRegion = zeros(1, 3);
msg = 'tag_getTvChannelClass: ';
%% Load SVM Model
% If SVM model has not been generated, generate one with
% multiclassLogoTrainer.m script.
svmModelFileURI = 'LogoModelRealDataWithOriginal.mat';
load(svmModelFileURI, 'classificationMdlSVM', 'tvChannelClasses', 'expectedLogoCorners');
if (exist('classificationMdlSVM', 'var')~=1) || (exist('tvChannelClasses', 'var')~=1) || (exist('expectedLogoCorners', 'var')~=1)
disp('Status: SVM Classification Model is corrupt.');
disp(['Status:', msg, 'Exiting...']);
return;
else
disp('Status: SVM Classification Model Loaded.');
featureVectorSize = length(classificationMdlSVM.PredictorNames);
end
%% Find TV Channel Class
corners = getTimedframeCorners(videoURI); disp('Status: Timed Frame Corners Extracted.');
cornerHeight = size(corners,1);
cornerWidth = size(corners,2);
numFrames = size(corners, 4);
currentEdgeField = zeros(cornerHeight, cornerWidth, 4);
timeAveragedEdgeField = zeros(cornerHeight, cornerWidth, 4);
for i = 1 : numFrames
alpha = getAlpha(i);
for j = 1 : 4
currentEdgeField(:,:,j) = edge(rgb2gray(corners(:,:,:,i,j)),'canny');
timeAveragedEdgeField(:,:,j) = alpha*timeAveragedEdgeField(:,:,j) + (1-alpha)*currentEdgeField(:,:,j);
end
end
disp('Status: Average Edge Fields calculated.');
trinarisationImage = zeros(cornerHeight, cornerWidth, 4);
binaryLogoMask = zeros(cornerHeight, cornerWidth, 4);
minIntesity = min(timeAveragedEdgeField(:));
maxIntesity = max(timeAveragedEdgeField(:));
for j = 1 : 4
[ trinarisationImage(:,:,j), binaryLogoMask(:,:,j) ] = hysteresis3d(timeAveragedEdgeField(:,:,j), 0.2, 0.7, minIntesity, maxIntesity);
end
disp('Status: Prominent Edges Extracted.');
closedLogoMask = zeros(cornerHeight, cornerWidth, 4);
holeFilledLogoMask = zeros(cornerHeight, cornerWidth, 4);
openedLogoMask = zeros(cornerHeight, cornerWidth, 4);
tvChannelClassesFound = [];
tvChannelCorners = [];
numClassesFound = 0;
disk5px = strel('disk',5);
for j = 1 : 4
fprintf('Status: Processing Corner %d.\n', j);
closedLogoMask(:,:,j) = imclose(binaryLogoMask(:,:,j), disk5px);
holeFilledLogoMask(:,:,j) = imfill(closedLogoMask(:,:,j),'holes');
openedLogoMask(:,:,j) = imopen(holeFilledLogoMask(:,:,j), disk5px);
CC = bwconncomp(openedLogoMask(:,:,j));
stats = regionprops(CC, 'BoundingBox', 'Area');
fprintf('Corner %d - Number of ConnComps = %d.\n', j, size(stats,1));
for k = 1 : size(stats,1)
fprintf('Status: Processing Corner %d - ConnComp %d.\n', j, k);
disp(stats(k));
if satisfyShapeConstraints(stats(k), j, cornerHeight, cornerWidth)
% logo has been detected
fprintf('Corner %d - ConnComp %d satisfies shape constraints.\n', j, k);
% classify the detected logo
gdFeatures = zeros(numFrames, featureVectorSize);
for m = 1 : numFrames
featureVector = getGridDescriptors(imcrop(corners(:,:,:,m,j), stats(k).BoundingBox));
gdFeatures(m,:) = featureVector(:);
end
labels = predict(classificationMdlSVM, gdFeatures);
mostOccuringLabel = mode(labels);
fprintf('Logo classified as: %s.\n', char(tvChannelClasses{mostOccuringLabel}));
% check if occurs in expected corner
if expectedLogoCorners(mostOccuringLabel) == j
% show the classified logo
numClassesFound = numClassesFound + 1;
tvChannelClassesFound(numClassesFound) = mostOccuringLabel;
tvChannelCorners(numClassesFound) = j;
else
disp('Logo does not occur in expected corner, so not considered.');
end
else
fprintf('Corner %d - ConnComp %d does not satisfy shape constraints.\n', j, k);
end
end
end
%% Return most occuring TV Channel Class
tvChannelCorner = 2; % By default corner is 2, if no tv channel found
temp = mode(tvChannelClassesFound);
if ~isnan(temp)
tvChannelClass = temp;
tvChannelCorners = tvChannelCorners(tvChannelClassesFound == tvChannelClass);
tvChannelCorner = mode(tvChannelCorners);
end
%% Find OCR Region
cornerSums = zeros(1, 4);
for i = 1 : 4
if i ~= tvChannelCorner
cornerSums(i) = sum(sum(binaryLogoMask(:,:,i)));
else
cornerSums(i) = 0;
end
end
[m, i] = max(cornerSums);
if (i == 3) || (i == 4)
% cricket score board covers the frame from left to right
CCL = bwconncomp(openedLogoMask(:,:,3));
CCR = bwconncomp(openedLogoMask(:,:,4));
stats = cat(1, regionprops(CCL, 'BoundingBox'), regionprops(CCR, 'BoundingBox'));
ocrRegion(1) = 3;
elseif i==1
% football score board covers only left part of screen
CC = bwconncomp(openedLogoMask(:,:,1));
stats = regionprops(CC, 'BoundingBox');
ocrRegion(1) = 1;
else
% mostly will never reach here, as logo occurs mostly here
CC = bwconncomp(openedLogoMask(:,:,2));
stats = regionprops(CC, 'BoundingBox');
ocrRegion(1) = 2;
end
minY = cornerHeight; maxY = 0;
for i = 1 : size(stats,1)
y = stats(i).BoundingBox(1,2);
if(y > maxY)
maxY = y;
end
if(y < minY)
minY = y;
end
end
ocrRegion(2) = minY;
ocrRegion(3) = maxY;
end