aboutsummaryrefslogtreecommitdiff
path: root/helium/heliumtextdetector.cpp
blob: 0f202df106a33aa6287225cff7cf7631abda64e4 (plain)
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
// Copyright 2006 Google Inc.
// All Rights Reserved.
// Author: <renn@google.com> (Marius Renn)
//
// Local includes
#include <time.h>
#include "clusterer.h"
#include "contourdetector.h"
#include "debugging.h"
#include "edgedetector.h"
#include "gaussiansmooth.h"
#include "heliumtextdetector.h"
#include "maxtracer.h"
#include "imageenhancer.h"
#include "image.h"
#include "quicksmooth.h"
#include "shapetree.h"
#include "sobeledgedetector.h"
#include "laplaceedgedetector.h"
#include "textclassifier.h"
#include "textvalidator.h"
#include "leptonica.h"

using namespace helium;


static void ShowTrace(ContourDetector& outliner, int trace_type,
                      int width, int height) {
  Mask mask(width, height);
  outliner.PlotTracesOnto(mask, trace_type);
  Image trace_image = Image::FromMask(mask);
  Leptonica::DisplayImage(trace_image);
}

static void ShowShapeTree(Clusterer& clusterer, ShapeTree& shapes,
                          int width, int height) {
  Image image(width, height);
  image.Clear();
  shapes.PaintShapes(image);
  clusterer.DrawClusterBounds(image);
  Leptonica::DisplayImage(image);
}

HeliumTextDetector::HeliumTextDetector()
  : parameters_(),
    clusterer_(),
    shapemaker_(),
    text_areas_(NULL),
    show_debug_(false) {
}

HeliumTextDetector::~HeliumTextDetector() {
  delete text_areas_;
  delete parameters_.edge_detector;
  delete parameters_.tracer;
}

void HeliumTextDetector::SetDefaultParameters() {
  parameters_.use_gaussian_smoothing = false;
  parameters_.gaussian_strength = 3;
  parameters_.edge_detector = new SobelEdgeDetector();
  // parameters_.edge_detector = new LaplaceEdgeDetector();
  parameters_.tracer = new MaxTracer(24);
  parameters_.trace_threshold = 16;
}

const TextAreas& HeliumTextDetector::GetTextAreas() {
  GetMutableTextAreas();
  return *text_areas_;
}

TextAreas* HeliumTextDetector::GetMutableTextAreas() {
  if (!text_areas_) {
    text_areas_ = new TextAreas(clusterer_.clusters());
  }
  return text_areas_;
}

void HeliumTextDetector::DetectText(const Image& image) {
  ASSERT(image.Valid());

  // Clean up any remains from last detection
  delete(text_areas_);
  text_areas_ = NULL;

  // Parameters set?
  ASSERT(parameters_.edge_detector && parameters_.tracer);

  // Smooth image
  Image smooth_image;
  if (parameters_.use_gaussian_smoothing) {
    GaussianSmooth gaussian_blur(parameters_.gaussian_strength);
    smooth_image = gaussian_blur.Smooth(image);
  } else {
    smooth_image.Copy(image);
    QuickSmooth::Smooth(smooth_image);
  }

  ImageEnhancer::EnhanceColors(smooth_image, kMinDynamicRange);

  // Edge detection
  EdgeDetector* detector = parameters_.edge_detector;
  GrayMap edges = detector->DetectEdges(smooth_image);
  ImageEnhancer::LocalContrast(edges);

  // Tracing
  TextClassifier text_classifier;
  Tracer* tracer = parameters_.tracer;
  tracer->set_trace_map(&edges);
  ContourDetector outliner(*tracer, text_classifier);
  outliner.DetectContours(edges,
                          parameters_.trace_threshold,
                          smooth_image);

  // Labeling
  shapemaker_.ClearShapes();
  shapemaker_.ConvertTraces(outliner.contours(), smooth_image);

  // Clustering
  TextValidator text_validator;
  clusterer_.ClearClusters();
  clusterer_.ClusterShapes(shapemaker_.shapes(), text_validator);

  if (show_debug_) {
    Leptonica::DisplayImage(smooth_image);
    Leptonica::DisplayGrayMap(edges);
    ShowTrace(outliner, TRACECLASS_TEXT, image.width(), image.height());
    ShowShapeTree(clusterer_, shapemaker_, image.width(), image.height());
  }
}