mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2025-01-18 14:41:36 +08:00
classify: Replace NULL by nullptr
Signed-off-by: Stefan Weil <sw@weilnetz.de>
This commit is contained in:
parent
57755a2754
commit
72ac460f96
@ -52,8 +52,8 @@ void AddAdaptedClass(ADAPT_TEMPLATES Templates,
|
||||
CLASS_ID ClassId) {
|
||||
INT_CLASS IntClass;
|
||||
|
||||
assert (Templates != NULL);
|
||||
assert (Class != NULL);
|
||||
assert (Templates != nullptr);
|
||||
assert (Class != nullptr);
|
||||
assert (LegalClassId (ClassId));
|
||||
assert (UnusedClassIdIn (Templates->Templates, ClassId));
|
||||
assert (Class->NumPermConfigs == 0);
|
||||
@ -61,7 +61,7 @@ void AddAdaptedClass(ADAPT_TEMPLATES Templates,
|
||||
IntClass = NewIntClass (1, 1);
|
||||
AddIntClass (Templates->Templates, ClassId, IntClass);
|
||||
|
||||
assert (Templates->Class[ClassId] == NULL);
|
||||
assert (Templates->Class[ClassId] == nullptr);
|
||||
Templates->Class[ClassId] = Class;
|
||||
|
||||
} /* AddAdaptedClass */
|
||||
@ -79,7 +79,7 @@ void AddAdaptedClass(ADAPT_TEMPLATES Templates,
|
||||
* @note History: Thu Mar 14 13:34:23 1991, DSJ, Created.
|
||||
*/
|
||||
void FreeTempConfig(TEMP_CONFIG Config) {
|
||||
assert (Config != NULL);
|
||||
assert (Config != nullptr);
|
||||
FreeBitVector (Config->Protos);
|
||||
free(Config);
|
||||
} /* FreeTempConfig */
|
||||
@ -92,7 +92,7 @@ void FreeTempProto(void *arg) {
|
||||
}
|
||||
|
||||
void FreePermConfig(PERM_CONFIG Config) {
|
||||
assert(Config != NULL);
|
||||
assert(Config != nullptr);
|
||||
delete [] Config->Ambigs;
|
||||
free(Config);
|
||||
}
|
||||
@ -123,7 +123,7 @@ ADAPT_CLASS NewAdaptedClass() {
|
||||
zero_all_bits (Class->PermConfigs, WordsInVectorOfSize (MAX_NUM_CONFIGS));
|
||||
|
||||
for (i = 0; i < MAX_NUM_CONFIGS; i++)
|
||||
TempConfigFor (Class, i) = NULL;
|
||||
TempConfigFor (Class, i) = nullptr;
|
||||
|
||||
return (Class);
|
||||
|
||||
@ -136,10 +136,10 @@ void free_adapted_class(ADAPT_CLASS adapt_class) {
|
||||
|
||||
for (i = 0; i < MAX_NUM_CONFIGS; i++) {
|
||||
if (ConfigIsPermanent (adapt_class, i)
|
||||
&& PermConfigFor (adapt_class, i) != NULL)
|
||||
&& PermConfigFor (adapt_class, i) != nullptr)
|
||||
FreePermConfig (PermConfigFor (adapt_class, i));
|
||||
else if (!ConfigIsPermanent (adapt_class, i)
|
||||
&& TempConfigFor (adapt_class, i) != NULL)
|
||||
&& TempConfigFor (adapt_class, i) != nullptr)
|
||||
FreeTempConfig (TempConfigFor (adapt_class, i));
|
||||
}
|
||||
FreeBitVector (adapt_class->PermProtos);
|
||||
@ -174,7 +174,7 @@ ADAPT_TEMPLATES Classify::NewAdaptedTemplates(bool InitFromUnicharset) {
|
||||
|
||||
/* Insert an empty class for each unichar id in unicharset */
|
||||
for (i = 0; i < MAX_NUM_CLASSES; i++) {
|
||||
Templates->Class[i] = NULL;
|
||||
Templates->Class[i] = nullptr;
|
||||
if (InitFromUnicharset && i < unicharset.size()) {
|
||||
AddAdaptedClass(Templates, NewAdaptedClass(), i);
|
||||
}
|
||||
@ -196,7 +196,7 @@ int Classify::GetFontinfoId(ADAPT_CLASS Class, uint8_t ConfigId) {
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void free_adapted_templates(ADAPT_TEMPLATES templates) {
|
||||
|
||||
if (templates != NULL) {
|
||||
if (templates != nullptr) {
|
||||
int i;
|
||||
for (i = 0; i < (templates->Templates)->NumClasses; i++)
|
||||
free_adapted_class (templates->Class[i]);
|
||||
@ -519,7 +519,7 @@ void Classify::WriteAdaptedTemplates(FILE *File, ADAPT_TEMPLATES Templates) {
|
||||
void WritePermConfig(FILE *File, PERM_CONFIG Config) {
|
||||
uint8_t NumAmbigs = 0;
|
||||
|
||||
assert (Config != NULL);
|
||||
assert (Config != nullptr);
|
||||
while (Config->Ambigs[NumAmbigs] > 0) ++NumAmbigs;
|
||||
|
||||
fwrite((char *) &NumAmbigs, sizeof(uint8_t), 1, File);
|
||||
@ -541,7 +541,7 @@ void WritePermConfig(FILE *File, PERM_CONFIG Config) {
|
||||
* @note History: Tue Mar 19 14:00:28 1991, DSJ, Created.
|
||||
*/
|
||||
void WriteTempConfig(FILE *File, TEMP_CONFIG Config) {
|
||||
assert (Config != NULL);
|
||||
assert (Config != nullptr);
|
||||
|
||||
fwrite ((char *) Config, sizeof (TEMP_CONFIG_STRUCT), 1, File);
|
||||
fwrite ((char *) Config->Protos, sizeof (uint32_t),
|
||||
|
@ -183,11 +183,11 @@ namespace tesseract {
|
||||
*
|
||||
*/
|
||||
void Classify::AdaptiveClassifier(TBLOB *Blob, BLOB_CHOICE_LIST *Choices) {
|
||||
assert(Choices != NULL);
|
||||
assert(Choices != nullptr);
|
||||
ADAPT_RESULTS *Results = new ADAPT_RESULTS;
|
||||
Results->Initialize();
|
||||
|
||||
ASSERT_HOST(AdaptedTemplates != NULL);
|
||||
ASSERT_HOST(AdaptedTemplates != nullptr);
|
||||
|
||||
DoAdaptiveMatch(Blob, Results);
|
||||
|
||||
@ -215,13 +215,13 @@ void Classify::AdaptiveClassifier(TBLOB *Blob, BLOB_CHOICE_LIST *Choices) {
|
||||
delete Results;
|
||||
} /* AdaptiveClassifier */
|
||||
|
||||
// If *win is NULL, sets it to a new ScrollView() object with title msg.
|
||||
// If *win is nullptr, sets it to a new ScrollView() object with title msg.
|
||||
// Clears the window and draws baselines.
|
||||
void Classify::RefreshDebugWindow(ScrollView **win, const char *msg,
|
||||
int y_offset, const TBOX &wbox) {
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
const int kSampleSpaceWidth = 500;
|
||||
if (*win == NULL) {
|
||||
if (*win == nullptr) {
|
||||
*win = new ScrollView(msg, 100, y_offset, kSampleSpaceWidth * 2, 200,
|
||||
kSampleSpaceWidth * 2, 200, true);
|
||||
}
|
||||
@ -238,17 +238,17 @@ void Classify::RefreshDebugWindow(ScrollView **win, const char *msg,
|
||||
|
||||
// Learns the given word using its chopped_word, seam_array, denorm,
|
||||
// box_word, best_state, and correct_text to learn both correctly and
|
||||
// incorrectly segmented blobs. If fontname is not NULL, then LearnBlob
|
||||
// incorrectly segmented blobs. If fontname is not nullptr, then LearnBlob
|
||||
// is called and the data will be saved in an internal buffer.
|
||||
// Otherwise AdaptToBlob is called for adaption within a document.
|
||||
void Classify::LearnWord(const char* fontname, WERD_RES* word) {
|
||||
int word_len = word->correct_text.size();
|
||||
if (word_len == 0) return;
|
||||
|
||||
float* thresholds = NULL;
|
||||
if (fontname == NULL) {
|
||||
float* thresholds = nullptr;
|
||||
if (fontname == nullptr) {
|
||||
// Adaption mode.
|
||||
if (!EnableLearning || word->best_choice == NULL)
|
||||
if (!EnableLearning || word->best_choice == nullptr)
|
||||
return; // Can't or won't adapt.
|
||||
|
||||
if (classify_learning_debug_level >= 1)
|
||||
@ -264,7 +264,7 @@ void Classify::LearnWord(const char* fontname, WERD_RES* word) {
|
||||
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (classify_debug_character_fragments) {
|
||||
if (learn_fragmented_word_debug_win_ != NULL) {
|
||||
if (learn_fragmented_word_debug_win_ != nullptr) {
|
||||
window_wait(learn_fragmented_word_debug_win_);
|
||||
}
|
||||
RefreshDebugWindow(&learn_fragments_debug_win_, "LearnPieces", 400,
|
||||
@ -281,7 +281,7 @@ void Classify::LearnWord(const char* fontname, WERD_RES* word) {
|
||||
tprintf("\nLearning %s\n", word->correct_text[ch].string());
|
||||
}
|
||||
if (word->correct_text[ch].length() > 0) {
|
||||
float threshold = thresholds != NULL ? thresholds[ch] : 0.0f;
|
||||
float threshold = thresholds != nullptr ? thresholds[ch] : 0.0f;
|
||||
|
||||
LearnPieces(fontname, start_blob, word->best_state[ch], threshold,
|
||||
CST_WHOLE, word->correct_text[ch].string(), word);
|
||||
@ -358,7 +358,7 @@ void Classify::LearnWord(const char* fontname, WERD_RES* word) {
|
||||
|
||||
// Builds a blob of length fragments, from the word, starting at start,
|
||||
// and then learns it, as having the given correct_text.
|
||||
// If fontname is not NULL, then LearnBlob is called and the data will be
|
||||
// If fontname is not nullptr, then LearnBlob is called and the data will be
|
||||
// saved in an internal buffer for static training.
|
||||
// Otherwise AdaptToBlob is called for adaption within a document.
|
||||
// threshold is a magic number required by AdaptToChar and generated by
|
||||
@ -381,7 +381,7 @@ void Classify::LearnPieces(const char* fontname, int start, int length,
|
||||
TBLOB* blob = word->chopped_word->blobs[start];
|
||||
// Rotate the blob if needed for classification.
|
||||
TBLOB* rotated_blob = blob->ClassifyNormalizeIfNeeded();
|
||||
if (rotated_blob == NULL)
|
||||
if (rotated_blob == nullptr)
|
||||
rotated_blob = blob;
|
||||
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
@ -394,14 +394,14 @@ void Classify::LearnPieces(const char* fontname, int start, int length,
|
||||
window_wait(learn_debug_win_);
|
||||
}
|
||||
if (classify_debug_character_fragments && segmentation == CST_FRAGMENT) {
|
||||
ASSERT_HOST(learn_fragments_debug_win_ != NULL); // set up in LearnWord
|
||||
ASSERT_HOST(learn_fragments_debug_win_ != nullptr); // set up in LearnWord
|
||||
blob->plot(learn_fragments_debug_win_,
|
||||
ScrollView::BLUE, ScrollView::BROWN);
|
||||
learn_fragments_debug_win_->Update();
|
||||
}
|
||||
#endif // GRAPHICS_DISABLED
|
||||
|
||||
if (fontname != NULL) {
|
||||
if (fontname != nullptr) {
|
||||
classify_norm_method.set_value(character); // force char norm spc 30/11/93
|
||||
tess_bn_matching.set_value(false); // turn it off
|
||||
tess_cn_matching.set_value(false);
|
||||
@ -412,16 +412,16 @@ void Classify::LearnPieces(const char* fontname, int start, int length,
|
||||
LearnBlob(fontname, rotated_blob, cn_denorm, fx_info, correct_text);
|
||||
} else if (unicharset.contains_unichar(correct_text)) {
|
||||
UNICHAR_ID class_id = unicharset.unichar_to_id(correct_text);
|
||||
int font_id = word->fontinfo != NULL
|
||||
int font_id = word->fontinfo != nullptr
|
||||
? fontinfo_table_.get_id(*word->fontinfo)
|
||||
: 0;
|
||||
if (classify_learning_debug_level >= 1)
|
||||
tprintf("Adapting to char = %s, thr= %g font_id= %d\n",
|
||||
unicharset.id_to_unichar(class_id), threshold, font_id);
|
||||
// If filename is not NULL we are doing recognition
|
||||
// If filename is not nullptr we are doing recognition
|
||||
// (as opposed to training), so we must have already set word fonts.
|
||||
AdaptToChar(rotated_blob, class_id, font_id, threshold, AdaptedTemplates);
|
||||
if (BackupAdaptedTemplates != NULL) {
|
||||
if (BackupAdaptedTemplates != nullptr) {
|
||||
// Adapt the backup templates too. They will be used if the primary gets
|
||||
// too full.
|
||||
AdaptToChar(rotated_blob, class_id, font_id, threshold,
|
||||
@ -457,11 +457,11 @@ void Classify::EndAdaptiveClassifier() {
|
||||
STRING Filename;
|
||||
FILE *File;
|
||||
|
||||
if (AdaptedTemplates != NULL &&
|
||||
if (AdaptedTemplates != nullptr &&
|
||||
classify_enable_adaptive_matcher && classify_save_adapted_templates) {
|
||||
Filename = imagefile + ADAPT_TEMPLATE_SUFFIX;
|
||||
File = fopen (Filename.string(), "wb");
|
||||
if (File == NULL)
|
||||
if (File == nullptr)
|
||||
cprintf ("Unable to save adapted templates to %s!\n", Filename.string());
|
||||
else {
|
||||
cprintf ("\nSaving adapted templates to %s ...", Filename.string());
|
||||
@ -472,36 +472,36 @@ void Classify::EndAdaptiveClassifier() {
|
||||
}
|
||||
}
|
||||
|
||||
if (AdaptedTemplates != NULL) {
|
||||
if (AdaptedTemplates != nullptr) {
|
||||
free_adapted_templates(AdaptedTemplates);
|
||||
AdaptedTemplates = NULL;
|
||||
AdaptedTemplates = nullptr;
|
||||
}
|
||||
if (BackupAdaptedTemplates != NULL) {
|
||||
if (BackupAdaptedTemplates != nullptr) {
|
||||
free_adapted_templates(BackupAdaptedTemplates);
|
||||
BackupAdaptedTemplates = NULL;
|
||||
BackupAdaptedTemplates = nullptr;
|
||||
}
|
||||
|
||||
if (PreTrainedTemplates != NULL) {
|
||||
if (PreTrainedTemplates != nullptr) {
|
||||
free_int_templates(PreTrainedTemplates);
|
||||
PreTrainedTemplates = NULL;
|
||||
PreTrainedTemplates = nullptr;
|
||||
}
|
||||
getDict().EndDangerousAmbigs();
|
||||
FreeNormProtos();
|
||||
if (AllProtosOn != NULL) {
|
||||
if (AllProtosOn != nullptr) {
|
||||
FreeBitVector(AllProtosOn);
|
||||
FreeBitVector(AllConfigsOn);
|
||||
FreeBitVector(AllConfigsOff);
|
||||
FreeBitVector(TempProtoMask);
|
||||
AllProtosOn = NULL;
|
||||
AllConfigsOn = NULL;
|
||||
AllConfigsOff = NULL;
|
||||
TempProtoMask = NULL;
|
||||
AllProtosOn = nullptr;
|
||||
AllConfigsOn = nullptr;
|
||||
AllConfigsOff = nullptr;
|
||||
TempProtoMask = nullptr;
|
||||
}
|
||||
delete shape_table_;
|
||||
shape_table_ = NULL;
|
||||
if (static_classifier_ != NULL) {
|
||||
shape_table_ = nullptr;
|
||||
if (static_classifier_ != nullptr) {
|
||||
delete static_classifier_;
|
||||
static_classifier_ = NULL;
|
||||
static_classifier_ = nullptr;
|
||||
}
|
||||
} /* EndAdaptiveClassifier */
|
||||
|
||||
@ -527,7 +527,7 @@ void Classify::EndAdaptiveClassifier() {
|
||||
void Classify::InitAdaptiveClassifier(TessdataManager* mgr) {
|
||||
if (!classify_enable_adaptive_matcher)
|
||||
return;
|
||||
if (AllProtosOn != NULL)
|
||||
if (AllProtosOn != nullptr)
|
||||
EndAdaptiveClassifier(); // Don't leak with multiple inits.
|
||||
|
||||
// If there is no language_data_path_prefix, the classifier will be
|
||||
@ -542,7 +542,7 @@ void Classify::InitAdaptiveClassifier(TessdataManager* mgr) {
|
||||
if (!shape_table_->DeSerialize(&fp)) {
|
||||
tprintf("Error loading shape table!\n");
|
||||
delete shape_table_;
|
||||
shape_table_ = NULL;
|
||||
shape_table_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -590,7 +590,7 @@ void Classify::InitAdaptiveClassifier(TessdataManager* mgr) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (AdaptedTemplates != NULL)
|
||||
if (AdaptedTemplates != nullptr)
|
||||
free_adapted_templates(AdaptedTemplates);
|
||||
AdaptedTemplates = NewAdaptedTemplates(true);
|
||||
}
|
||||
@ -603,16 +603,16 @@ void Classify::ResetAdaptiveClassifierInternal() {
|
||||
}
|
||||
free_adapted_templates(AdaptedTemplates);
|
||||
AdaptedTemplates = NewAdaptedTemplates(true);
|
||||
if (BackupAdaptedTemplates != NULL)
|
||||
if (BackupAdaptedTemplates != nullptr)
|
||||
free_adapted_templates(BackupAdaptedTemplates);
|
||||
BackupAdaptedTemplates = NULL;
|
||||
BackupAdaptedTemplates = nullptr;
|
||||
NumAdaptationsFailed = 0;
|
||||
}
|
||||
|
||||
// If there are backup adapted templates, switches to those, otherwise resets
|
||||
// the main adaptive classifier (because it is full.)
|
||||
void Classify::SwitchAdaptiveClassifier() {
|
||||
if (BackupAdaptedTemplates == NULL) {
|
||||
if (BackupAdaptedTemplates == nullptr) {
|
||||
ResetAdaptiveClassifierInternal();
|
||||
return;
|
||||
}
|
||||
@ -622,13 +622,13 @@ void Classify::SwitchAdaptiveClassifier() {
|
||||
}
|
||||
free_adapted_templates(AdaptedTemplates);
|
||||
AdaptedTemplates = BackupAdaptedTemplates;
|
||||
BackupAdaptedTemplates = NULL;
|
||||
BackupAdaptedTemplates = nullptr;
|
||||
NumAdaptationsFailed = 0;
|
||||
}
|
||||
|
||||
// Resets the backup adaptive classifier to empty.
|
||||
void Classify::StartBackupAdaptiveClassifier() {
|
||||
if (BackupAdaptedTemplates != NULL)
|
||||
if (BackupAdaptedTemplates != nullptr)
|
||||
free_adapted_templates(BackupAdaptedTemplates);
|
||||
BackupAdaptedTemplates = NewAdaptedTemplates(true);
|
||||
}
|
||||
@ -834,7 +834,7 @@ int Classify::GetAdaptiveFeatures(TBLOB *Blob,
|
||||
* @note History: Thu May 30 14:25:06 1991, DSJ, Created.
|
||||
*/
|
||||
bool Classify::AdaptableWord(WERD_RES* word) {
|
||||
if (word->best_choice == NULL) return false;
|
||||
if (word->best_choice == nullptr) return false;
|
||||
int BestChoiceLength = word->best_choice->length();
|
||||
float adaptable_score =
|
||||
getDict().segment_penalty_dict_case_ok + ADAPTABLE_WERD_ADJUSTMENT;
|
||||
@ -886,7 +886,7 @@ void Classify::AdaptToChar(TBLOB* Blob, CLASS_ID ClassId, int FontinfoId,
|
||||
|
||||
int_result.unichar_id = ClassId;
|
||||
Class = adaptive_templates->Class[ClassId];
|
||||
assert(Class != NULL);
|
||||
assert(Class != nullptr);
|
||||
if (IsEmptyAdaptedClass(Class)) {
|
||||
InitAdaptedClass(Blob, ClassId, FontinfoId, Class, adaptive_templates);
|
||||
} else {
|
||||
@ -969,7 +969,7 @@ void Classify::DisplayAdaptedChar(TBLOB* blob, INT_CLASS_STRUCT* int_class) {
|
||||
TrainingSample* sample =
|
||||
BlobToTrainingSample(*blob, classify_nonlinear_norm, &fx_info,
|
||||
&bl_features);
|
||||
if (sample == NULL) return;
|
||||
if (sample == nullptr) return;
|
||||
|
||||
UnicharRating int_result;
|
||||
im_.Match(int_class, AllProtosOn, AllConfigsOn,
|
||||
@ -1079,7 +1079,7 @@ void Classify::AmbigClassifier(
|
||||
uint8_t* CharNormArray = new uint8_t[unicharset.size()];
|
||||
UnicharRating int_result;
|
||||
|
||||
results->BlobLength = GetCharNormFeature(fx_info, templates, NULL,
|
||||
results->BlobLength = GetCharNormFeature(fx_info, templates, nullptr,
|
||||
CharNormArray);
|
||||
bool debug = matcher_debug_level >= 2 || classify_debug_level > 1;
|
||||
if (debug)
|
||||
@ -1098,7 +1098,7 @@ void Classify::AmbigClassifier(
|
||||
classify_adapt_feature_threshold, NO_DEBUG,
|
||||
matcher_debug_separate_windows);
|
||||
|
||||
ExpandShapesAndApplyCorrections(NULL, debug, class_id, bottom, top, 0,
|
||||
ExpandShapesAndApplyCorrections(nullptr, debug, class_id, bottom, top, 0,
|
||||
results->BlobLength,
|
||||
classify_integer_matcher_multiplier,
|
||||
CharNormArray, &int_result, results);
|
||||
@ -1125,9 +1125,9 @@ void Classify::MasterMatcher(INT_TEMPLATES templates,
|
||||
UnicharRating int_result;
|
||||
for (int c = 0; c < results.size(); c++) {
|
||||
CLASS_ID class_id = results[c].Class;
|
||||
BIT_VECTOR protos = classes != NULL ? classes[class_id]->PermProtos
|
||||
BIT_VECTOR protos = classes != nullptr ? classes[class_id]->PermProtos
|
||||
: AllProtosOn;
|
||||
BIT_VECTOR configs = classes != NULL ? classes[class_id]->PermConfigs
|
||||
BIT_VECTOR configs = classes != nullptr ? classes[class_id]->PermConfigs
|
||||
: AllConfigsOn;
|
||||
|
||||
int_result.unichar_id = class_id;
|
||||
@ -1155,7 +1155,7 @@ void Classify::ExpandShapesAndApplyCorrections(
|
||||
float cp_rating, int blob_length, int matcher_multiplier,
|
||||
const uint8_t* cn_factors,
|
||||
UnicharRating* int_result, ADAPT_RESULTS* final_results) {
|
||||
if (classes != NULL) {
|
||||
if (classes != nullptr) {
|
||||
// Adapted result. Convert configs to fontinfo_ids.
|
||||
int_result->adapted = true;
|
||||
for (int f = 0; f < int_result->fonts.size(); ++f) {
|
||||
@ -1170,7 +1170,7 @@ void Classify::ExpandShapesAndApplyCorrections(
|
||||
ClassAndConfigIDToFontOrShapeID(class_id,
|
||||
int_result->fonts[f].fontinfo_id);
|
||||
}
|
||||
if (shape_table_ != NULL) {
|
||||
if (shape_table_ != nullptr) {
|
||||
// Two possible cases:
|
||||
// 1. Flat shapetable. All unichar-ids of the shapes referenced by
|
||||
// int_result->fonts are the same. In this case build a new vector of
|
||||
@ -1293,7 +1293,7 @@ UNICHAR_ID *Classify::BaselineClassifier(
|
||||
TBLOB *Blob, const GenericVector<INT_FEATURE_STRUCT>& int_features,
|
||||
const INT_FX_RESULT_STRUCT& fx_info,
|
||||
ADAPT_TEMPLATES Templates, ADAPT_RESULTS *Results) {
|
||||
if (int_features.empty()) return NULL;
|
||||
if (int_features.empty()) return nullptr;
|
||||
uint8_t* CharNormArray = new uint8_t[unicharset.size()];
|
||||
ClearCharNormArray(CharNormArray);
|
||||
|
||||
@ -1312,7 +1312,7 @@ UNICHAR_ID *Classify::BaselineClassifier(
|
||||
delete [] CharNormArray;
|
||||
CLASS_ID ClassId = Results->best_unichar_id;
|
||||
if (ClassId == INVALID_UNICHAR_ID || Results->best_match_index < 0)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
return Templates->Class[ClassId]->
|
||||
Config[Results->match[Results->best_match_index].config].Perm->Ambigs;
|
||||
@ -1382,7 +1382,7 @@ int Classify::CharNormTrainingSample(bool pruner_only,
|
||||
|
||||
PruneClasses(PreTrainedTemplates, num_features, keep_this, sample.features(),
|
||||
pruner_norm_array,
|
||||
shape_table_ != NULL ? &shapetable_cutoffs_[0] : CharNormCutoffs,
|
||||
shape_table_ != nullptr ? &shapetable_cutoffs_[0] : CharNormCutoffs,
|
||||
&adapt_results->CPResults);
|
||||
delete [] pruner_norm_array;
|
||||
if (keep_this >= 0) {
|
||||
@ -1399,7 +1399,7 @@ int Classify::CharNormTrainingSample(bool pruner_only,
|
||||
} else {
|
||||
MasterMatcher(PreTrainedTemplates, num_features, sample.features(),
|
||||
char_norm_array,
|
||||
NULL, matcher_debug_flags,
|
||||
nullptr, matcher_debug_flags,
|
||||
classify_integer_matcher_multiplier,
|
||||
blob_box, adapt_results->CPResults, adapt_results);
|
||||
// Convert master matcher results to output format.
|
||||
@ -1446,7 +1446,7 @@ void Classify::ClassifyAsNoise(ADAPT_RESULTS *results) {
|
||||
void Classify::ConvertMatchesToChoices(const DENORM& denorm, const TBOX& box,
|
||||
ADAPT_RESULTS *Results,
|
||||
BLOB_CHOICE_LIST *Choices) {
|
||||
assert(Choices != NULL);
|
||||
assert(Choices != nullptr);
|
||||
FLOAT32 Rating;
|
||||
FLOAT32 Certainty;
|
||||
BLOB_CHOICE_IT temp_it;
|
||||
@ -1459,7 +1459,7 @@ void Classify::ConvertMatchesToChoices(const DENORM& denorm, const TBOX& box,
|
||||
// grapheme fragments) and more, so use double the size of the biggest shape
|
||||
// if that is more than the default.
|
||||
int max_matches = MAX_MATCHES;
|
||||
if (shape_table_ != NULL) {
|
||||
if (shape_table_ != nullptr) {
|
||||
max_matches = shape_table_->MaxNumUnichars() * 2;
|
||||
if (max_matches < MAX_MATCHES)
|
||||
max_matches = MAX_MATCHES;
|
||||
@ -1469,7 +1469,7 @@ void Classify::ConvertMatchesToChoices(const DENORM& denorm, const TBOX& box,
|
||||
for (int i = 0; i < Results->match.size(); i++) {
|
||||
const UnicharRating& result = Results->match[i];
|
||||
bool adapted = result.adapted;
|
||||
bool current_is_frag = (unicharset.get_fragment(result.unichar_id) != NULL);
|
||||
bool current_is_frag = (unicharset.get_fragment(result.unichar_id) != nullptr);
|
||||
if (temp_it.length()+1 == max_matches &&
|
||||
!contains_nonfrag && current_is_frag) {
|
||||
continue; // look for a non-fragmented character to fill the
|
||||
@ -1532,12 +1532,12 @@ void Classify::ConvertMatchesToChoices(const DENORM& denorm, const TBOX& box,
|
||||
*/
|
||||
void Classify::DebugAdaptiveClassifier(TBLOB *blob,
|
||||
ADAPT_RESULTS *Results) {
|
||||
if (static_classifier_ == NULL) return;
|
||||
if (static_classifier_ == nullptr) return;
|
||||
INT_FX_RESULT_STRUCT fx_info;
|
||||
GenericVector<INT_FEATURE_STRUCT> bl_features;
|
||||
TrainingSample* sample =
|
||||
BlobToTrainingSample(*blob, false, &fx_info, &bl_features);
|
||||
if (sample == NULL) return;
|
||||
if (sample == nullptr) return;
|
||||
static_classifier_->DebugDisplay(*sample, blob->denorm().pix(),
|
||||
Results->best_unichar_id);
|
||||
} /* DebugAdaptiveClassifier */
|
||||
@ -1574,7 +1574,7 @@ void Classify::DoAdaptiveMatch(TBLOB *Blob, ADAPT_RESULTS *Results) {
|
||||
TrainingSample* sample =
|
||||
BlobToTrainingSample(*Blob, classify_nonlinear_norm, &fx_info,
|
||||
&bl_features);
|
||||
if (sample == NULL) return;
|
||||
if (sample == nullptr) return;
|
||||
|
||||
if (AdaptedTemplates->NumPermClasses < matcher_permanent_classes_min ||
|
||||
tess_cn_matching) {
|
||||
@ -1600,7 +1600,7 @@ void Classify::DoAdaptiveMatch(TBLOB *Blob, ADAPT_RESULTS *Results) {
|
||||
// Force the blob to be classified as noise
|
||||
// if the results contain only fragments.
|
||||
// TODO(daria): verify that this is better than
|
||||
// just adding a NULL classification.
|
||||
// just adding a nullptr classification.
|
||||
if (!Results->HasNonfragment || Results->match.empty())
|
||||
ClassifyAsNoise(Results);
|
||||
delete sample;
|
||||
@ -1635,9 +1635,9 @@ UNICHAR_ID *Classify::GetAmbiguities(TBLOB *Blob,
|
||||
TrainingSample* sample =
|
||||
BlobToTrainingSample(*Blob, classify_nonlinear_norm, &fx_info,
|
||||
&bl_features);
|
||||
if (sample == NULL) {
|
||||
if (sample == nullptr) {
|
||||
delete Results;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CharNormClassifier(Blob, *sample, Results);
|
||||
@ -1675,7 +1675,7 @@ bool Classify::LooksLikeGarbage(TBLOB *blob) {
|
||||
}
|
||||
for (ratings_it.mark_cycle_pt(); !ratings_it.cycled_list();
|
||||
ratings_it.forward()) {
|
||||
if (unicharset.get_fragment(ratings_it.data()->unichar_id()) != NULL) {
|
||||
if (unicharset.get_fragment(ratings_it.data()->unichar_id()) != nullptr) {
|
||||
continue;
|
||||
}
|
||||
float certainty = ratings_it.data()->certainty();
|
||||
@ -1729,15 +1729,15 @@ int Classify::GetCharNormFeature(const INT_FX_RESULT_STRUCT& fx_info,
|
||||
return IntCastRounded(fx_info.Length / kStandardFeatureLength);
|
||||
} /* GetCharNormFeature */
|
||||
|
||||
// Computes the char_norm_array for the unicharset and, if not NULL, the
|
||||
// Computes the char_norm_array for the unicharset and, if not nullptr, the
|
||||
// pruner_array as appropriate according to the existence of the shape_table.
|
||||
void Classify::ComputeCharNormArrays(FEATURE_STRUCT* norm_feature,
|
||||
INT_TEMPLATES_STRUCT* templates,
|
||||
uint8_t* char_norm_array,
|
||||
uint8_t* pruner_array) {
|
||||
ComputeIntCharNormArray(*norm_feature, char_norm_array);
|
||||
if (pruner_array != NULL) {
|
||||
if (shape_table_ == NULL) {
|
||||
if (pruner_array != nullptr) {
|
||||
if (shape_table_ == nullptr) {
|
||||
ComputeIntCharNormArray(*norm_feature, pruner_array);
|
||||
} else {
|
||||
memset(pruner_array, UINT8_MAX,
|
||||
@ -2101,7 +2101,7 @@ void Classify::RemoveBadMatches(ADAPT_RESULTS *Results) {
|
||||
if (match.rating >= BadMatchThreshold) {
|
||||
if (!unicharset.get_isalpha(match.unichar_id) ||
|
||||
strstr(romans,
|
||||
unicharset.id_to_unichar(match.unichar_id)) != NULL) {
|
||||
unicharset.id_to_unichar(match.unichar_id)) != nullptr) {
|
||||
} else if (unicharset.eq(match.unichar_id, "l") &&
|
||||
scored_one < BadMatchThreshold) {
|
||||
Results->match[Next].unichar_id = unichar_id_one;
|
||||
@ -2158,13 +2158,13 @@ void Classify::RemoveExtraPuncs(ADAPT_RESULTS *Results) {
|
||||
const UnicharRating& match = Results->match[Next];
|
||||
bool keep = true;
|
||||
if (strstr(punc_chars,
|
||||
unicharset.id_to_unichar(match.unichar_id)) != NULL) {
|
||||
unicharset.id_to_unichar(match.unichar_id)) != nullptr) {
|
||||
if (punc_count >= 2)
|
||||
keep = false;
|
||||
punc_count++;
|
||||
} else {
|
||||
if (strstr(digit_chars,
|
||||
unicharset.id_to_unichar(match.unichar_id)) != NULL) {
|
||||
unicharset.id_to_unichar(match.unichar_id)) != nullptr) {
|
||||
if (digit_count >= 1)
|
||||
keep = false;
|
||||
digit_count++;
|
||||
@ -2254,7 +2254,7 @@ void Classify::ShowBestMatchFor(int shape_id,
|
||||
STRING Classify::ClassIDToDebugStr(const INT_TEMPLATES_STRUCT* templates,
|
||||
int class_id, int config_id) const {
|
||||
STRING class_string;
|
||||
if (templates == PreTrainedTemplates && shape_table_ != NULL) {
|
||||
if (templates == PreTrainedTemplates && shape_table_ != nullptr) {
|
||||
int shape_id = ClassAndConfigIDToFontOrShapeID(class_id, config_id);
|
||||
class_string = shape_table_->DebugStr(shape_id);
|
||||
} else {
|
||||
@ -2309,10 +2309,10 @@ bool Classify::TempConfigReliable(CLASS_ID class_id,
|
||||
// enough times all the characters represented by the ambigs vector.
|
||||
const UnicharIdVector *ambigs =
|
||||
getDict().getUnicharAmbigs().AmbigsForAdaption(class_id);
|
||||
int ambigs_size = (ambigs == NULL) ? 0 : ambigs->size();
|
||||
int ambigs_size = (ambigs == nullptr) ? 0 : ambigs->size();
|
||||
for (int ambig = 0; ambig < ambigs_size; ++ambig) {
|
||||
ADAPT_CLASS ambig_class = AdaptedTemplates->Class[(*ambigs)[ambig]];
|
||||
assert(ambig_class != NULL);
|
||||
assert(ambig_class != nullptr);
|
||||
if (ambig_class->NumPermConfigs == 0 &&
|
||||
ambig_class->MaxNumTimesSeen <
|
||||
matcher_min_examples_for_prototyping) {
|
||||
@ -2333,7 +2333,7 @@ bool Classify::TempConfigReliable(CLASS_ID class_id,
|
||||
void Classify::UpdateAmbigsGroup(CLASS_ID class_id, TBLOB *Blob) {
|
||||
const UnicharIdVector *ambigs =
|
||||
getDict().getUnicharAmbigs().ReverseAmbigsForAdaption(class_id);
|
||||
int ambigs_size = (ambigs == NULL) ? 0 : ambigs->size();
|
||||
int ambigs_size = (ambigs == nullptr) ? 0 : ambigs->size();
|
||||
if (classify_learning_debug_level >= 1) {
|
||||
tprintf("Running UpdateAmbigsGroup for %s class_id=%d\n",
|
||||
getDict().getUnicharset().debug_str(class_id).string(), class_id);
|
||||
@ -2345,7 +2345,7 @@ void Classify::UpdateAmbigsGroup(CLASS_ID class_id, TBLOB *Blob) {
|
||||
if (ConfigIsPermanent(ambigs_class, cfg)) continue;
|
||||
const TEMP_CONFIG config =
|
||||
TempConfigFor(AdaptedTemplates->Class[ambig_class_id], cfg);
|
||||
if (config != NULL && TempConfigReliable(ambig_class_id, config)) {
|
||||
if (config != nullptr && TempConfigReliable(ambig_class_id, config)) {
|
||||
if (classify_learning_debug_level >= 1) {
|
||||
tprintf("Making config %d of %s permanent\n", cfg,
|
||||
getDict().getUnicharset().debug_str(
|
||||
|
@ -51,7 +51,7 @@ void ExtractFontName(const STRING& filename, STRING* fontname) {
|
||||
const char *basename = strrchr(filename.string(), '/');
|
||||
const char *firstdot = strchr(basename ? basename : filename.string(), '.');
|
||||
const char *lastdot = strrchr(filename.string(), '.');
|
||||
if (firstdot != lastdot && firstdot != NULL && lastdot != NULL) {
|
||||
if (firstdot != lastdot && firstdot != nullptr && lastdot != nullptr) {
|
||||
++firstdot;
|
||||
*fontname = firstdot;
|
||||
fontname->truncate_at(lastdot - firstdot);
|
||||
|
@ -159,9 +159,9 @@ Classify::Classify()
|
||||
this->params()),
|
||||
double_MEMBER(speckle_rating_penalty, 10.0,
|
||||
"Penalty to add to worst rating for noise", this->params()),
|
||||
shape_table_(NULL),
|
||||
shape_table_(nullptr),
|
||||
dict_(this),
|
||||
static_classifier_(NULL) {
|
||||
static_classifier_(nullptr) {
|
||||
fontinfo_table_.set_compare_callback(
|
||||
NewPermanentTessCallback(CompareFontInfo));
|
||||
fontinfo_table_.set_clear_callback(
|
||||
@ -170,20 +170,20 @@ Classify::Classify()
|
||||
NewPermanentTessCallback(CompareFontSet));
|
||||
fontset_table_.set_clear_callback(
|
||||
NewPermanentTessCallback(FontSetDeleteCallback));
|
||||
AdaptedTemplates = NULL;
|
||||
BackupAdaptedTemplates = NULL;
|
||||
PreTrainedTemplates = NULL;
|
||||
AllProtosOn = NULL;
|
||||
AllConfigsOn = NULL;
|
||||
AllConfigsOff = NULL;
|
||||
TempProtoMask = NULL;
|
||||
NormProtos = NULL;
|
||||
AdaptedTemplates = nullptr;
|
||||
BackupAdaptedTemplates = nullptr;
|
||||
PreTrainedTemplates = nullptr;
|
||||
AllProtosOn = nullptr;
|
||||
AllConfigsOn = nullptr;
|
||||
AllConfigsOff = nullptr;
|
||||
TempProtoMask = nullptr;
|
||||
NormProtos = nullptr;
|
||||
|
||||
NumAdaptationsFailed = 0;
|
||||
|
||||
learn_debug_win_ = NULL;
|
||||
learn_fragmented_word_debug_win_ = NULL;
|
||||
learn_fragments_debug_win_ = NULL;
|
||||
learn_debug_win_ = nullptr;
|
||||
learn_fragmented_word_debug_win_ = nullptr;
|
||||
learn_fragments_debug_win_ = nullptr;
|
||||
}
|
||||
|
||||
Classify::~Classify() {
|
||||
|
@ -120,14 +120,14 @@ class Classify : public CCStruct {
|
||||
|
||||
// Learns the given word using its chopped_word, seam_array, denorm,
|
||||
// box_word, best_state, and correct_text to learn both correctly and
|
||||
// incorrectly segmented blobs. If fontname is not NULL, then LearnBlob
|
||||
// incorrectly segmented blobs. If fontname is not nullptr, then LearnBlob
|
||||
// is called and the data will be saved in an internal buffer.
|
||||
// Otherwise AdaptToBlob is called for adaption within a document.
|
||||
void LearnWord(const char* fontname, WERD_RES* word);
|
||||
|
||||
// Builds a blob of length fragments, from the word, starting at start,
|
||||
// and then learns it, as having the given correct_text.
|
||||
// If fontname is not NULL, then LearnBlob is called and the data will be
|
||||
// If fontname is not nullptr, then LearnBlob is called and the data will be
|
||||
// saved in an internal buffer for static training.
|
||||
// Otherwise AdaptToBlob is called for adaption within a document.
|
||||
// threshold is a magic number required by AdaptToChar and generated by
|
||||
@ -269,7 +269,7 @@ class Classify : public CCStruct {
|
||||
INT_TEMPLATES templates,
|
||||
uint8_t* pruner_norm_array,
|
||||
uint8_t* char_norm_array);
|
||||
// Computes the char_norm_array for the unicharset and, if not NULL, the
|
||||
// Computes the char_norm_array for the unicharset and, if not nullptr, the
|
||||
// pruner_array as appropriate according to the existence of the shape_table.
|
||||
// The norm_feature is deleted as it is almost certainly no longer needed.
|
||||
void ComputeCharNormArrays(FEATURE_STRUCT* norm_feature,
|
||||
@ -318,7 +318,7 @@ class Classify : public CCStruct {
|
||||
// (x,y) position and angle as measured counterclockwise from the vector
|
||||
// <-1, 0>, from blob using two normalizations defined by bl_denorm and
|
||||
// cn_denorm. See SetpuBLCNDenorms for definitions.
|
||||
// If outline_cn_counts is not NULL, on return it contains the cumulative
|
||||
// If outline_cn_counts is not nullptr, on return it contains the cumulative
|
||||
// number of cn features generated for each outline in the blob (in order).
|
||||
// Thus after the first outline, there were (*outline_cn_counts)[0] features,
|
||||
// after the second outline, there were (*outline_cn_counts)[1] features etc.
|
||||
|
@ -407,7 +407,7 @@ MakeClusterer (int16_t SampleSize, const PARAM_DESC ParamDesc[]) {
|
||||
Clusterer->NumChar = 0;
|
||||
|
||||
// init fields which will not be used initially
|
||||
Clusterer->Root = NULL;
|
||||
Clusterer->Root = nullptr;
|
||||
Clusterer->ProtoList = NIL_LIST;
|
||||
|
||||
// maintain a copy of param descriptors in the clusterer data structure
|
||||
@ -430,7 +430,7 @@ MakeClusterer (int16_t SampleSize, const PARAM_DESC ParamDesc[]) {
|
||||
// Initialize cache of histogram buckets to minimize recomputing them.
|
||||
for (int d = 0; d < DISTRIBUTION_COUNT; ++d) {
|
||||
for (int c = 0; c < MAXBUCKETS + 1 - MINBUCKETS; ++c)
|
||||
Clusterer->bucket_cache[d][c] = NULL;
|
||||
Clusterer->bucket_cache[d][c] = nullptr;
|
||||
}
|
||||
|
||||
return Clusterer;
|
||||
@ -458,7 +458,7 @@ SAMPLE* MakeSample(CLUSTERER * Clusterer, const FLOAT32* Feature,
|
||||
int i;
|
||||
|
||||
// see if the samples have already been clustered - if so trap an error
|
||||
if (Clusterer->Root != NULL)
|
||||
if (Clusterer->Root != nullptr)
|
||||
DoError (ALREADYCLUSTERED,
|
||||
"Can't add samples after they have been clustered");
|
||||
|
||||
@ -469,8 +469,8 @@ SAMPLE* MakeSample(CLUSTERER * Clusterer, const FLOAT32* Feature,
|
||||
Sample->Clustered = FALSE;
|
||||
Sample->Prototype = FALSE;
|
||||
Sample->SampleCount = 1;
|
||||
Sample->Left = NULL;
|
||||
Sample->Right = NULL;
|
||||
Sample->Left = nullptr;
|
||||
Sample->Right = nullptr;
|
||||
Sample->CharID = CharID;
|
||||
|
||||
for (i = 0; i < Clusterer->SampleSize; i++)
|
||||
@ -511,7 +511,7 @@ SAMPLE* MakeSample(CLUSTERER * Clusterer, const FLOAT32* Feature,
|
||||
*/
|
||||
LIST ClusterSamples(CLUSTERER *Clusterer, CLUSTERCONFIG *Config) {
|
||||
//only create cluster tree if samples have never been clustered before
|
||||
if (Clusterer->Root == NULL)
|
||||
if (Clusterer->Root == nullptr)
|
||||
CreateClusterTree(Clusterer);
|
||||
|
||||
//deallocate the old prototype list if one exists
|
||||
@ -525,7 +525,7 @@ LIST ClusterSamples(CLUSTERER *Clusterer, CLUSTERCONFIG *Config) {
|
||||
LIST proto_list = Clusterer->ProtoList;
|
||||
iterate(proto_list) {
|
||||
PROTOTYPE *proto = reinterpret_cast<PROTOTYPE *>(first_node(proto_list));
|
||||
proto->Cluster = NULL;
|
||||
proto->Cluster = nullptr;
|
||||
}
|
||||
return Clusterer->ProtoList;
|
||||
} // ClusterSamples
|
||||
@ -535,7 +535,7 @@ LIST ClusterSamples(CLUSTERER *Clusterer, CLUSTERCONFIG *Config) {
|
||||
* specified data structure. It will not, however, free
|
||||
* the memory used by the prototype list. The pointers to
|
||||
* the clusters for each prototype in the list will be set
|
||||
* to NULL to indicate that the cluster data structures no
|
||||
* to nullptr to indicate that the cluster data structures no
|
||||
* longer exist. Any sample lists that have been obtained
|
||||
* via calls to GetSamples are no longer valid.
|
||||
* @param Clusterer pointer to data structure to be freed
|
||||
@ -544,16 +544,16 @@ LIST ClusterSamples(CLUSTERER *Clusterer, CLUSTERCONFIG *Config) {
|
||||
* @note History: 6/6/89, DSJ, Created.
|
||||
*/
|
||||
void FreeClusterer(CLUSTERER *Clusterer) {
|
||||
if (Clusterer != NULL) {
|
||||
if (Clusterer != nullptr) {
|
||||
free(Clusterer->ParamDesc);
|
||||
if (Clusterer->KDTree != NULL)
|
||||
if (Clusterer->KDTree != nullptr)
|
||||
FreeKDTree (Clusterer->KDTree);
|
||||
if (Clusterer->Root != NULL)
|
||||
if (Clusterer->Root != nullptr)
|
||||
FreeCluster (Clusterer->Root);
|
||||
// Free up all used buckets structures.
|
||||
for (int d = 0; d < DISTRIBUTION_COUNT; ++d) {
|
||||
for (int c = 0; c < MAXBUCKETS + 1 - MINBUCKETS; ++c)
|
||||
if (Clusterer->bucket_cache[d][c] != NULL)
|
||||
if (Clusterer->bucket_cache[d][c] != nullptr)
|
||||
FreeBuckets(Clusterer->bucket_cache[d][c]);
|
||||
}
|
||||
|
||||
@ -588,7 +588,7 @@ void FreePrototype(void *arg) { //PROTOTYPE *Prototype)
|
||||
PROTOTYPE *Prototype = (PROTOTYPE *) arg;
|
||||
|
||||
// unmark the corresponding cluster (if there is one
|
||||
if (Prototype->Cluster != NULL)
|
||||
if (Prototype->Cluster != nullptr)
|
||||
Prototype->Cluster->Prototype = FALSE;
|
||||
|
||||
// deallocate the prototype statistics and then the prototype itself
|
||||
@ -609,11 +609,11 @@ void FreePrototype(void *arg) { //PROTOTYPE *Prototype)
|
||||
* a leaf it is returned. Otherwise, the right subcluster
|
||||
* is pushed on the list and we continue the search in the
|
||||
* left subcluster. This continues until a leaf is found.
|
||||
* If all samples have been found, NULL is returned.
|
||||
* If all samples have been found, nullptr is returned.
|
||||
* InitSampleSearch() must be called
|
||||
* before NextSample() to initialize the search.
|
||||
* @param SearchState ptr to list containing clusters to be searched
|
||||
* @return Pointer to the next leaf cluster (sample) or NULL.
|
||||
* @return Pointer to the next leaf cluster (sample) or nullptr.
|
||||
* @note Exceptions: None
|
||||
* @note History: 6/16/89, DSJ, Created.
|
||||
*/
|
||||
@ -621,11 +621,11 @@ CLUSTER *NextSample(LIST *SearchState) {
|
||||
CLUSTER *Cluster;
|
||||
|
||||
if (*SearchState == NIL_LIST)
|
||||
return (NULL);
|
||||
return (nullptr);
|
||||
Cluster = (CLUSTER *) first_node (*SearchState);
|
||||
*SearchState = pop (*SearchState);
|
||||
while (TRUE) {
|
||||
if (Cluster->Left == NULL)
|
||||
if (Cluster->Left == nullptr)
|
||||
return (Cluster);
|
||||
*SearchState = push (*SearchState, Cluster->Right);
|
||||
Cluster = Cluster->Left;
|
||||
@ -725,7 +725,7 @@ void CreateClusterTree(CLUSTERER *Clusterer) {
|
||||
PotentialCluster->Neighbor =
|
||||
FindNearestNeighbor(context.tree, PotentialCluster->Cluster,
|
||||
&HeapEntry.key);
|
||||
if (PotentialCluster->Neighbor != NULL) {
|
||||
if (PotentialCluster->Neighbor != nullptr) {
|
||||
context.heap->Push(&HeapEntry);
|
||||
}
|
||||
}
|
||||
@ -737,7 +737,7 @@ void CreateClusterTree(CLUSTERER *Clusterer) {
|
||||
PotentialCluster->Neighbor =
|
||||
FindNearestNeighbor(context.tree, PotentialCluster->Cluster,
|
||||
&HeapEntry.key);
|
||||
if (PotentialCluster->Neighbor != NULL) {
|
||||
if (PotentialCluster->Neighbor != nullptr) {
|
||||
context.heap->Push(&HeapEntry);
|
||||
}
|
||||
}
|
||||
@ -748,7 +748,7 @@ void CreateClusterTree(CLUSTERER *Clusterer) {
|
||||
|
||||
// free up the memory used by the K-D tree, heap, and temp clusters
|
||||
FreeKDTree(context.tree);
|
||||
Clusterer->KDTree = NULL;
|
||||
Clusterer->KDTree = nullptr;
|
||||
delete context.heap;
|
||||
free(context.candidates);
|
||||
} // CreateClusterTree
|
||||
@ -772,7 +772,7 @@ void MakePotentialClusters(ClusteringContext *context,
|
||||
FindNearestNeighbor(context->tree,
|
||||
context->candidates[next].Cluster,
|
||||
&HeapEntry.key);
|
||||
if (context->candidates[next].Neighbor != NULL) {
|
||||
if (context->candidates[next].Neighbor != nullptr) {
|
||||
context->heap->Push(&HeapEntry);
|
||||
context->next++;
|
||||
}
|
||||
@ -783,13 +783,13 @@ void MakePotentialClusters(ClusteringContext *context,
|
||||
* neighbor of the specified cluster. It actually uses the
|
||||
* kd routines to find the 2 nearest neighbors since one of them
|
||||
* will be the original cluster. A pointer to the nearest
|
||||
* neighbor is returned, if it can be found, otherwise NULL is
|
||||
* neighbor is returned, if it can be found, otherwise nullptr is
|
||||
* returned. The distance between the 2 nodes is placed
|
||||
* in the specified variable.
|
||||
* @param Tree kd-tree to search in for nearest neighbor
|
||||
* @param Cluster cluster whose nearest neighbor is to be found
|
||||
* @param Distance ptr to variable to report distance found
|
||||
* @return Pointer to the nearest neighbor of Cluster, or NULL
|
||||
* @return Pointer to the nearest neighbor of Cluster, or nullptr
|
||||
* @note Exceptions: none
|
||||
* @note History: 5/29/89, DSJ, Created.
|
||||
* 7/13/89, DSJ, Removed visibility of kd-tree node data struct
|
||||
@ -811,7 +811,7 @@ FindNearestNeighbor(KDTREE * Tree, CLUSTER * Cluster, FLOAT32 * Distance)
|
||||
|
||||
// search for the nearest neighbor that is not the cluster itself
|
||||
*Distance = MAXDISTANCE;
|
||||
BestNeighbor = NULL;
|
||||
BestNeighbor = nullptr;
|
||||
for (i = 0; i < NumberOfNeighbors; i++) {
|
||||
if ((Dist[i] < *Distance) && (Neighbor[i] != Cluster)) {
|
||||
*Distance = Dist[i];
|
||||
@ -928,7 +928,7 @@ void ComputePrototypes(CLUSTERER *Clusterer, CLUSTERCONFIG *Config) {
|
||||
|
||||
// use a stack to keep track of clusters waiting to be processed
|
||||
// initially the only cluster on the stack is the root cluster
|
||||
if (Clusterer->Root != NULL)
|
||||
if (Clusterer->Root != nullptr)
|
||||
ClusterStack = push (NIL_LIST, Clusterer->Root);
|
||||
|
||||
// loop until we have analyzed all clusters which are potential prototypes
|
||||
@ -939,7 +939,7 @@ void ComputePrototypes(CLUSTERER *Clusterer, CLUSTERCONFIG *Config) {
|
||||
Cluster = (CLUSTER *) first_node (ClusterStack);
|
||||
ClusterStack = pop (ClusterStack);
|
||||
Prototype = MakePrototype(Clusterer, Config, Cluster);
|
||||
if (Prototype != NULL) {
|
||||
if (Prototype != nullptr) {
|
||||
Clusterer->ProtoList = push (Clusterer->ProtoList, Prototype);
|
||||
}
|
||||
else {
|
||||
@ -956,13 +956,13 @@ void ComputePrototypes(CLUSTERER *Clusterer, CLUSTERCONFIG *Config) {
|
||||
* cluster to perform a statistical analysis, then a prototype
|
||||
* is generated but labelled as insignificant. If the
|
||||
* dimensions of the cluster are not independent, no prototype
|
||||
* is generated and NULL is returned. If a prototype can be
|
||||
* is generated and nullptr is returned. If a prototype can be
|
||||
* found that matches the desired distribution then a pointer
|
||||
* to it is returned, otherwise NULL is returned.
|
||||
* to it is returned, otherwise nullptr is returned.
|
||||
* @param Clusterer data structure holding cluster tree
|
||||
* @param Config parameters used to control prototype generation
|
||||
* @param Cluster cluster to be made into a prototype
|
||||
* @return Pointer to new prototype or NULL
|
||||
* @return Pointer to new prototype or nullptr
|
||||
* @note Exceptions: None
|
||||
* @note History: 6/19/89, DSJ, Created.
|
||||
*/
|
||||
@ -975,7 +975,7 @@ PROTOTYPE *MakePrototype(CLUSTERER *Clusterer,
|
||||
|
||||
// filter out clusters which contain samples from the same character
|
||||
if (MultipleCharSamples (Clusterer, Cluster, Config->MaxIllegal))
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
// compute the covariance matrix and ranges for the cluster
|
||||
Statistics =
|
||||
@ -987,7 +987,7 @@ PROTOTYPE *MakePrototype(CLUSTERER *Clusterer,
|
||||
Proto = MakeDegenerateProto(
|
||||
Clusterer->SampleSize, Cluster, Statistics, Config->ProtoStyle,
|
||||
(int32_t) (Config->MinSamples * Clusterer->NumChar));
|
||||
if (Proto != NULL) {
|
||||
if (Proto != nullptr) {
|
||||
FreeStatistics(Statistics);
|
||||
return Proto;
|
||||
}
|
||||
@ -995,12 +995,12 @@ PROTOTYPE *MakePrototype(CLUSTERER *Clusterer,
|
||||
if (!Independent(Clusterer->ParamDesc, Clusterer->SampleSize,
|
||||
Statistics->CoVariance, Config->Independence)) {
|
||||
FreeStatistics(Statistics);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (HOTELLING && Config->ProtoStyle == elliptical) {
|
||||
Proto = TestEllipticalProto(Clusterer, Config, Cluster, Statistics);
|
||||
if (Proto != NULL) {
|
||||
if (Proto != nullptr) {
|
||||
FreeStatistics(Statistics);
|
||||
return Proto;
|
||||
}
|
||||
@ -1024,10 +1024,10 @@ PROTOTYPE *MakePrototype(CLUSTERER *Clusterer,
|
||||
break;
|
||||
case automatic:
|
||||
Proto = MakeSphericalProto(Clusterer, Cluster, Statistics, Buckets);
|
||||
if (Proto != NULL)
|
||||
if (Proto != nullptr)
|
||||
break;
|
||||
Proto = MakeEllipticalProto(Clusterer, Cluster, Statistics, Buckets);
|
||||
if (Proto != NULL)
|
||||
if (Proto != nullptr)
|
||||
break;
|
||||
Proto = MakeMixedProto(Clusterer, Cluster, Statistics, Buckets,
|
||||
Config->Confidence);
|
||||
@ -1047,14 +1047,14 @@ PROTOTYPE *MakePrototype(CLUSTERER *Clusterer,
|
||||
* also degenerate if it does not have at least MinSamples
|
||||
* samples in it.
|
||||
*
|
||||
* If the cluster is not degenerate, NULL is returned.
|
||||
* If the cluster is not degenerate, nullptr is returned.
|
||||
*
|
||||
* @param N number of dimensions
|
||||
* @param Cluster cluster being analyzed
|
||||
* @param Statistics statistical info about cluster
|
||||
* @param Style type of prototype to be generated
|
||||
* @param MinSamples minimum number of samples in a cluster
|
||||
* @return Pointer to degenerate prototype or NULL.
|
||||
* @return Pointer to degenerate prototype or nullptr.
|
||||
* @note Exceptions: None
|
||||
* @note History: 6/20/89, DSJ, Created.
|
||||
* 7/12/89, DSJ, Changed name and added check for 0 stddev.
|
||||
@ -1066,7 +1066,7 @@ PROTOTYPE *MakeDegenerateProto( //this was MinSample
|
||||
STATISTICS *Statistics,
|
||||
PROTOSTYLE Style,
|
||||
int32_t MinSamples) {
|
||||
PROTOTYPE *Proto = NULL;
|
||||
PROTOTYPE *Proto = nullptr;
|
||||
|
||||
if (MinSamples < MINSAMPLESNEEDED)
|
||||
MinSamples = MINSAMPLESNEEDED;
|
||||
@ -1094,13 +1094,13 @@ PROTOTYPE *MakeDegenerateProto( //this was MinSample
|
||||
* there is a statistically significant difference between
|
||||
* the sub-clusters that would be made if the cluster were to
|
||||
* be split. If not, then a new prototype is formed and
|
||||
* returned to the caller. If there is, then NULL is returned
|
||||
* returned to the caller. If there is, then nullptr is returned
|
||||
* to the caller.
|
||||
* @param Clusterer data struct containing samples being clustered
|
||||
* @param Config provides the magic number of samples that make a good cluster
|
||||
* @param Cluster cluster to be made into an elliptical prototype
|
||||
* @param Statistics statistical info about cluster
|
||||
* @return Pointer to new elliptical prototype or NULL.
|
||||
* @return Pointer to new elliptical prototype or nullptr.
|
||||
*/
|
||||
PROTOTYPE *TestEllipticalProto(CLUSTERER *Clusterer,
|
||||
CLUSTERCONFIG *Config,
|
||||
@ -1117,11 +1117,11 @@ PROTOTYPE *TestEllipticalProto(CLUSTERER *Clusterer,
|
||||
int N = Clusterer->SampleSize;
|
||||
CLUSTER* Left = Cluster->Left;
|
||||
CLUSTER* Right = Cluster->Right;
|
||||
if (Left == NULL || Right == NULL)
|
||||
return NULL;
|
||||
if (Left == nullptr || Right == nullptr)
|
||||
return nullptr;
|
||||
int TotalDims = Left->SampleCount + Right->SampleCount;
|
||||
if (TotalDims < N + 1 || TotalDims < 2)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
const int kMatrixSize = N * N * sizeof(FLOAT32);
|
||||
FLOAT32 *Covariance = static_cast<FLOAT32 *>(Emalloc(kMatrixSize));
|
||||
FLOAT32 *Inverse = static_cast<FLOAT32 *>(Emalloc(kMatrixSize));
|
||||
@ -1193,19 +1193,19 @@ PROTOTYPE *TestEllipticalProto(CLUSTERER *Clusterer,
|
||||
if (F < FTarget) {
|
||||
return NewEllipticalProto (Clusterer->SampleSize, Cluster, Statistics);
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine tests the specified cluster to see if it can
|
||||
* be approximated by a spherical normal distribution. If it
|
||||
* can be, then a new prototype is formed and returned to the
|
||||
* caller. If it can't be, then NULL is returned to the caller.
|
||||
* caller. If it can't be, then nullptr is returned to the caller.
|
||||
* @param Clusterer data struct containing samples being clustered
|
||||
* @param Cluster cluster to be made into a spherical prototype
|
||||
* @param Statistics statistical info about cluster
|
||||
* @param Buckets histogram struct used to analyze distribution
|
||||
* @return Pointer to new spherical prototype or NULL.
|
||||
* @return Pointer to new spherical prototype or nullptr.
|
||||
* @note Exceptions: None
|
||||
* @note History: 6/1/89, DSJ, Created.
|
||||
*/
|
||||
@ -1213,7 +1213,7 @@ PROTOTYPE *MakeSphericalProto(CLUSTERER *Clusterer,
|
||||
CLUSTER *Cluster,
|
||||
STATISTICS *Statistics,
|
||||
BUCKETS *Buckets) {
|
||||
PROTOTYPE *Proto = NULL;
|
||||
PROTOTYPE *Proto = nullptr;
|
||||
int i;
|
||||
|
||||
// check that each dimension is a normal distribution
|
||||
@ -1237,12 +1237,12 @@ PROTOTYPE *MakeSphericalProto(CLUSTERER *Clusterer,
|
||||
* This routine tests the specified cluster to see if it can
|
||||
* be approximated by an elliptical normal distribution. If it
|
||||
* can be, then a new prototype is formed and returned to the
|
||||
* caller. If it can't be, then NULL is returned to the caller.
|
||||
* caller. If it can't be, then nullptr is returned to the caller.
|
||||
* @param Clusterer data struct containing samples being clustered
|
||||
* @param Cluster cluster to be made into an elliptical prototype
|
||||
* @param Statistics statistical info about cluster
|
||||
* @param Buckets histogram struct used to analyze distribution
|
||||
* @return Pointer to new elliptical prototype or NULL.
|
||||
* @return Pointer to new elliptical prototype or nullptr.
|
||||
* @note Exceptions: None
|
||||
* @note History: 6/12/89, DSJ, Created.
|
||||
*/
|
||||
@ -1250,7 +1250,7 @@ PROTOTYPE *MakeEllipticalProto(CLUSTERER *Clusterer,
|
||||
CLUSTER *Cluster,
|
||||
STATISTICS *Statistics,
|
||||
BUCKETS *Buckets) {
|
||||
PROTOTYPE *Proto = NULL;
|
||||
PROTOTYPE *Proto = nullptr;
|
||||
int i;
|
||||
|
||||
// check that each dimension is a normal distribution
|
||||
@ -1278,13 +1278,13 @@ PROTOTYPE *MakeEllipticalProto(CLUSTERER *Clusterer,
|
||||
* in order: normal, random, uniform. If each dimension can
|
||||
* be represented by one of these distributions,
|
||||
* then a new prototype is formed and returned to the
|
||||
* caller. If it can't be, then NULL is returned to the caller.
|
||||
* caller. If it can't be, then nullptr is returned to the caller.
|
||||
* @param Clusterer data struct containing samples being clustered
|
||||
* @param Cluster cluster to be made into a prototype
|
||||
* @param Statistics statistical info about cluster
|
||||
* @param NormalBuckets histogram struct used to analyze distribution
|
||||
* @param Confidence confidence level for alternate distributions
|
||||
* @return Pointer to new mixed prototype or NULL.
|
||||
* @return Pointer to new mixed prototype or nullptr.
|
||||
* @note Exceptions: None
|
||||
* @note History: 6/12/89, DSJ, Created.
|
||||
*/
|
||||
@ -1295,8 +1295,8 @@ PROTOTYPE *MakeMixedProto(CLUSTERER *Clusterer,
|
||||
FLOAT64 Confidence) {
|
||||
PROTOTYPE *Proto;
|
||||
int i;
|
||||
BUCKETS *UniformBuckets = NULL;
|
||||
BUCKETS *RandomBuckets = NULL;
|
||||
BUCKETS *UniformBuckets = nullptr;
|
||||
BUCKETS *RandomBuckets = nullptr;
|
||||
|
||||
// create a mixed proto to work on - initially assume all dimensions normal*/
|
||||
Proto = NewMixedProto (Clusterer->SampleSize, Cluster, Statistics);
|
||||
@ -1312,7 +1312,7 @@ PROTOTYPE *MakeMixedProto(CLUSTERER *Clusterer,
|
||||
if (DistributionOK (NormalBuckets))
|
||||
continue;
|
||||
|
||||
if (RandomBuckets == NULL)
|
||||
if (RandomBuckets == nullptr)
|
||||
RandomBuckets =
|
||||
GetBuckets(Clusterer, D_random, Cluster->SampleCount, Confidence);
|
||||
MakeDimRandom (i, Proto, &(Clusterer->ParamDesc[i]));
|
||||
@ -1321,7 +1321,7 @@ PROTOTYPE *MakeMixedProto(CLUSTERER *Clusterer,
|
||||
if (DistributionOK (RandomBuckets))
|
||||
continue;
|
||||
|
||||
if (UniformBuckets == NULL)
|
||||
if (UniformBuckets == nullptr)
|
||||
UniformBuckets =
|
||||
GetBuckets(Clusterer, uniform, Cluster->SampleCount, Confidence);
|
||||
MakeDimUniform(i, Proto, Statistics);
|
||||
@ -1334,7 +1334,7 @@ PROTOTYPE *MakeMixedProto(CLUSTERER *Clusterer,
|
||||
// if any dimension failed to match a distribution, discard the proto
|
||||
if (i < Clusterer->SampleSize) {
|
||||
FreePrototype(Proto);
|
||||
Proto = NULL;
|
||||
Proto = nullptr;
|
||||
}
|
||||
return (Proto);
|
||||
} // MakeMixedProto
|
||||
@ -1438,7 +1438,7 @@ ComputeStatistics (int16_t N, PARAM_DESC ParamDesc[], CLUSTER * Cluster) {
|
||||
}
|
||||
// find each sample in the cluster and merge it into the statistics
|
||||
InitSampleSearch(SearchState, Cluster);
|
||||
while ((Sample = NextSample (&SearchState)) != NULL) {
|
||||
while ((Sample = NextSample (&SearchState)) != nullptr) {
|
||||
for (i = 0; i < N; i++) {
|
||||
Distance[i] = Sample->Mean[i] - Cluster->Mean[i];
|
||||
if (ParamDesc[i].Circular) {
|
||||
@ -1606,7 +1606,7 @@ PROTOTYPE *NewSimpleProto(int16_t N, CLUSTER *Cluster) {
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
Proto->Mean[i] = Cluster->Mean[i];
|
||||
Proto->Distrib = NULL;
|
||||
Proto->Distrib = nullptr;
|
||||
|
||||
Proto->Significant = TRUE;
|
||||
Proto->Merged = FALSE;
|
||||
@ -1695,7 +1695,7 @@ BUCKETS *GetBuckets(CLUSTERER* clusterer,
|
||||
clusterer->bucket_cache[Distribution][NumberOfBuckets - MINBUCKETS];
|
||||
|
||||
// If a matching bucket structure is not found, make one and save it.
|
||||
if (Buckets == NULL) {
|
||||
if (Buckets == nullptr) {
|
||||
Buckets = MakeBuckets(Distribution, SampleCount, Confidence);
|
||||
clusterer->bucket_cache[Distribution][NumberOfBuckets - MINBUCKETS] =
|
||||
Buckets;
|
||||
@ -1888,7 +1888,7 @@ ComputeChiSquared (uint16_t DegreesOfFreedom, FLOAT64 Alpha)
|
||||
OldChiSquared = (CHISTRUCT *) first_node (search (ChiWith[DegreesOfFreedom],
|
||||
&SearchKey, AlphaMatch));
|
||||
|
||||
if (OldChiSquared == NULL) {
|
||||
if (OldChiSquared == nullptr) {
|
||||
OldChiSquared = NewChiStruct (DegreesOfFreedom, Alpha);
|
||||
OldChiSquared->ChiSquared = Solve (ChiArea, OldChiSquared,
|
||||
(FLOAT64) DegreesOfFreedom,
|
||||
@ -2005,7 +2005,7 @@ void FillBuckets(BUCKETS *Buckets,
|
||||
|
||||
InitSampleSearch(SearchState, Cluster);
|
||||
i = 0;
|
||||
while ((Sample = NextSample (&SearchState)) != NULL) {
|
||||
while ((Sample = NextSample (&SearchState)) != nullptr) {
|
||||
if (Sample->Mean[Dim] > Mean)
|
||||
BucketID = Buckets->NumberOfBuckets - 1;
|
||||
else if (Sample->Mean[Dim] < Mean)
|
||||
@ -2021,7 +2021,7 @@ void FillBuckets(BUCKETS *Buckets,
|
||||
else {
|
||||
// search for all samples in the cluster and add to histogram buckets
|
||||
InitSampleSearch(SearchState, Cluster);
|
||||
while ((Sample = NextSample (&SearchState)) != NULL) {
|
||||
while ((Sample = NextSample (&SearchState)) != nullptr) {
|
||||
switch (Buckets->Distribution) {
|
||||
case normal:
|
||||
BucketID = NormalBucket (ParamDesc, Sample->Mean[Dim],
|
||||
@ -2181,7 +2181,7 @@ void FreeBuckets(BUCKETS *buckets) {
|
||||
* @note History: 6/6/89, DSJ, Created.
|
||||
*/
|
||||
void FreeCluster(CLUSTER *Cluster) {
|
||||
if (Cluster != NULL) {
|
||||
if (Cluster != nullptr) {
|
||||
FreeCluster (Cluster->Left);
|
||||
FreeCluster (Cluster->Right);
|
||||
free(Cluster);
|
||||
@ -2466,7 +2466,7 @@ MultipleCharSamples (CLUSTERER * Clusterer,
|
||||
CLUSTER * Cluster, FLOAT32 MaxIllegal)
|
||||
#define ILLEGAL_CHAR 2
|
||||
{
|
||||
static BOOL8 *CharFlags = NULL;
|
||||
static BOOL8 *CharFlags = nullptr;
|
||||
static int32_t NumFlags = 0;
|
||||
int i;
|
||||
LIST SearchState;
|
||||
@ -2491,7 +2491,7 @@ CLUSTER * Cluster, FLOAT32 MaxIllegal)
|
||||
|
||||
// find each sample in the cluster and check if we have seen it before
|
||||
InitSampleSearch(SearchState, Cluster);
|
||||
while ((Sample = NextSample (&SearchState)) != NULL) {
|
||||
while ((Sample = NextSample (&SearchState)) != nullptr) {
|
||||
CharID = Sample->CharID;
|
||||
if (CharFlags[CharID] == FALSE) {
|
||||
CharFlags[CharID] = TRUE;
|
||||
|
@ -102,7 +102,7 @@ typedef struct {
|
||||
} SAMPLELIST;
|
||||
|
||||
// low level cluster tree analysis routines.
|
||||
#define InitSampleSearch(S,C) (((C)==NULL)?(S=NIL_LIST):(S=push(NIL_LIST,(C))))
|
||||
#define InitSampleSearch(S,C) (((C)==nullptr)?(S=NIL_LIST):(S=push(NIL_LIST,(C))))
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Public Function Prototypes
|
||||
|
@ -130,7 +130,7 @@ PROTOTYPE *ReadPrototype(TFile *fp, uint16_t N) {
|
||||
return nullptr;
|
||||
}
|
||||
Proto = (PROTOTYPE *)Emalloc(sizeof(PROTOTYPE));
|
||||
Proto->Cluster = NULL;
|
||||
Proto->Cluster = nullptr;
|
||||
if (sig_token[0] == 's')
|
||||
Proto->Significant = TRUE;
|
||||
else
|
||||
@ -154,23 +154,23 @@ PROTOTYPE *ReadPrototype(TFile *fp, uint16_t N) {
|
||||
if (SampleCount < 0) DoError(ILLEGALSAMPLECOUNT, "Illegal sample count");
|
||||
Proto->NumSamples = SampleCount;
|
||||
|
||||
Proto->Mean = ReadNFloats(fp, N, NULL);
|
||||
if (Proto->Mean == NULL) DoError(ILLEGALMEANSPEC, "Illegal prototype mean");
|
||||
Proto->Mean = ReadNFloats(fp, N, nullptr);
|
||||
if (Proto->Mean == nullptr) DoError(ILLEGALMEANSPEC, "Illegal prototype mean");
|
||||
|
||||
switch (Proto->Style) {
|
||||
case spherical:
|
||||
if (ReadNFloats(fp, 1, &(Proto->Variance.Spherical)) == NULL)
|
||||
if (ReadNFloats(fp, 1, &(Proto->Variance.Spherical)) == nullptr)
|
||||
DoError(ILLEGALVARIANCESPEC, "Illegal prototype variance");
|
||||
Proto->Magnitude.Spherical =
|
||||
1.0 / sqrt((double)(2.0 * PI * Proto->Variance.Spherical));
|
||||
Proto->TotalMagnitude = pow(Proto->Magnitude.Spherical, (float)N);
|
||||
Proto->LogMagnitude = log((double)Proto->TotalMagnitude);
|
||||
Proto->Weight.Spherical = 1.0 / Proto->Variance.Spherical;
|
||||
Proto->Distrib = NULL;
|
||||
Proto->Distrib = nullptr;
|
||||
break;
|
||||
case elliptical:
|
||||
Proto->Variance.Elliptical = ReadNFloats(fp, N, NULL);
|
||||
if (Proto->Variance.Elliptical == NULL)
|
||||
Proto->Variance.Elliptical = ReadNFloats(fp, N, nullptr);
|
||||
if (Proto->Variance.Elliptical == nullptr)
|
||||
DoError(ILLEGALVARIANCESPEC, "Illegal prototype variance");
|
||||
Proto->Magnitude.Elliptical = (FLOAT32 *)Emalloc(N * sizeof(FLOAT32));
|
||||
Proto->Weight.Elliptical = (FLOAT32 *)Emalloc(N * sizeof(FLOAT32));
|
||||
@ -182,7 +182,7 @@ PROTOTYPE *ReadPrototype(TFile *fp, uint16_t N) {
|
||||
Proto->TotalMagnitude *= Proto->Magnitude.Elliptical[i];
|
||||
}
|
||||
Proto->LogMagnitude = log((double)Proto->TotalMagnitude);
|
||||
Proto->Distrib = NULL;
|
||||
Proto->Distrib = nullptr;
|
||||
break;
|
||||
default:
|
||||
Efree(Proto);
|
||||
@ -194,14 +194,14 @@ PROTOTYPE *ReadPrototype(TFile *fp, uint16_t N) {
|
||||
|
||||
/**
|
||||
* This routine reads N floats from the specified text file
|
||||
* and places them into Buffer. If Buffer is NULL, a buffer
|
||||
* and places them into Buffer. If Buffer is nullptr, a buffer
|
||||
* is created and passed back to the caller. If EOF is
|
||||
* encountered before any floats can be read, NULL is
|
||||
* encountered before any floats can be read, nullptr is
|
||||
* returned.
|
||||
* @param fp open text file to read floats from
|
||||
* @param N number of floats to read
|
||||
* @param Buffer pointer to buffer to place floats into
|
||||
* @return Pointer to buffer holding floats or NULL if EOF
|
||||
* @return Pointer to buffer holding floats or nullptr if EOF
|
||||
* @note Globals: None
|
||||
* @note Exceptions: ILLEGALFLOAT
|
||||
* @note History: 6/6/89, DSJ, Created.
|
||||
@ -215,7 +215,7 @@ FLOAT32 *ReadNFloats(TFile *fp, uint16_t N, FLOAT32 Buffer[]) {
|
||||
}
|
||||
bool needs_free = false;
|
||||
|
||||
if (Buffer == NULL) {
|
||||
if (Buffer == nullptr) {
|
||||
Buffer = static_cast<FLOAT32 *>(Emalloc(N * sizeof(FLOAT32)));
|
||||
needs_free = true;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ void Classify::ReadNewCutoffs(TFile* fp, CLASS_CUTOFF_ARRAY Cutoffs) {
|
||||
int Cutoff;
|
||||
int i;
|
||||
|
||||
if (shape_table_ != NULL) {
|
||||
if (shape_table_ != nullptr) {
|
||||
if (!shapetable_cutoffs_.DeSerialize(fp)) {
|
||||
tprintf("Error during read of shapetable pffmtable!\n");
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ double ErrorCounter::ComputeErrorRate(ShapeClassifier* classifier,
|
||||
TrainingSample* mutable_sample = it->MutableSample();
|
||||
int page_index = mutable_sample->page_num();
|
||||
Pix* page_pix = 0 <= page_index && page_index < page_images.size()
|
||||
? page_images[page_index] : NULL;
|
||||
? page_images[page_index] : nullptr;
|
||||
// No debug, no keep this.
|
||||
classifier->UnicharClassifySample(*mutable_sample, page_pix, 0,
|
||||
INVALID_UNICHAR_ID, &results);
|
||||
@ -88,7 +88,7 @@ double ErrorCounter::ComputeErrorRate(ShapeClassifier* classifier,
|
||||
unscaled_error = counter.ReportErrors(report_level, boosting_mode,
|
||||
fontinfo_table,
|
||||
*it, unichar_error, fonts_report);
|
||||
if (scaled_error != NULL) *scaled_error = counter.scaled_error_;
|
||||
if (scaled_error != nullptr) *scaled_error = counter.scaled_error_;
|
||||
if (report_level > 1) {
|
||||
// It is useful to know the time in microseconds/char.
|
||||
tprintf("Errors computed in %.2fs at %.1f μs/char\n",
|
||||
@ -121,7 +121,7 @@ void ErrorCounter::DebugNewErrors(
|
||||
TrainingSample* mutable_sample = it->MutableSample();
|
||||
int page_index = mutable_sample->page_num();
|
||||
Pix* page_pix = 0 <= page_index && page_index < page_images.size()
|
||||
? page_images[page_index] : NULL;
|
||||
? page_images[page_index] : nullptr;
|
||||
// No debug, no keep this.
|
||||
old_classifier->UnicharClassifySample(*mutable_sample, page_pix, 0,
|
||||
INVALID_UNICHAR_ID, &results);
|
||||
@ -335,8 +335,8 @@ bool ErrorCounter::AccumulateJunk(bool debug,
|
||||
// error rate to return.
|
||||
// The fontinfo_table from MasterTrainer provides the names of fonts.
|
||||
// The it determines the current subset of the training samples.
|
||||
// If not NULL, the top-choice unichar error rate is saved in unichar_error.
|
||||
// If not NULL, the report string is saved in fonts_report.
|
||||
// If not nullptr, the top-choice unichar error rate is saved in unichar_error.
|
||||
// If not nullptr, the report string is saved in fonts_report.
|
||||
// (Ignoring report_level).
|
||||
double ErrorCounter::ReportErrors(int report_level, CountTypes boosting_mode,
|
||||
const FontInfoTable& fontinfo_table,
|
||||
@ -352,7 +352,7 @@ double ErrorCounter::ReportErrors(int report_level, CountTypes boosting_mode,
|
||||
totals += font_counts_[f];
|
||||
STRING font_report;
|
||||
if (ReportString(false, font_counts_[f], &font_report)) {
|
||||
if (fonts_report != NULL) {
|
||||
if (fonts_report != nullptr) {
|
||||
*fonts_report += fontinfo_table.get(f).name;
|
||||
*fonts_report += ": ";
|
||||
*fonts_report += font_report;
|
||||
@ -367,7 +367,7 @@ double ErrorCounter::ReportErrors(int report_level, CountTypes boosting_mode,
|
||||
// Report the totals.
|
||||
STRING total_report;
|
||||
bool any_results = ReportString(true, totals, &total_report);
|
||||
if (fonts_report != NULL && fonts_report->length() == 0) {
|
||||
if (fonts_report != nullptr && fonts_report->length() == 0) {
|
||||
// Make sure we return something even if there were no samples.
|
||||
*fonts_report = "NoSamplesFound: ";
|
||||
*fonts_report += total_report;
|
||||
@ -421,7 +421,7 @@ double ErrorCounter::ReportErrors(int report_level, CountTypes boosting_mode,
|
||||
if (!ComputeRates(totals, rates))
|
||||
return 0.0;
|
||||
// Set output values if asked for.
|
||||
if (unichar_error != NULL)
|
||||
if (unichar_error != nullptr)
|
||||
*unichar_error = rates[CT_UNICHAR_TOP1_ERR];
|
||||
return rates[boosting_mode];
|
||||
}
|
||||
|
@ -107,12 +107,12 @@ class ErrorCounter {
|
||||
// scaled_error output, and setting the is_error flag in the samples.
|
||||
// * The fontinfo_table is used to get string font names for the debug
|
||||
// output, and also to count font attributes errors.
|
||||
// * The page_images vector may contain a Pix* (which may be NULL) for each
|
||||
// * The page_images vector may contain a Pix* (which may be nullptr) for each
|
||||
// page index assigned to the samples.
|
||||
// * The it provides encapsulated iteration over some sample set.
|
||||
// * The outputs unichar_error, scaled_error and totals_report are all
|
||||
// optional.
|
||||
// * If not NULL, unichar error gets the top1 unichar error rate.
|
||||
// * If not nullptr, unichar error gets the top1 unichar error rate.
|
||||
// * Scaled_error gets the error chosen by boosting_mode weighted by the
|
||||
// weights on the samples.
|
||||
// * Fonts_report gets a string summarizing the error rates for each font in
|
||||
@ -181,8 +181,8 @@ class ErrorCounter {
|
||||
// error rate to return.
|
||||
// The fontinfo_table from MasterTrainer provides the names of fonts.
|
||||
// The it determines the current subset of the training samples.
|
||||
// If not NULL, the top-choice unichar error rate is saved in unichar_error.
|
||||
// If not NULL, the report string is saved in fonts_report.
|
||||
// If not nullptr, the top-choice unichar error rate is saved in unichar_error.
|
||||
// If not nullptr, the report string is saved in fonts_report.
|
||||
// (Ignoring report_level).
|
||||
double ReportErrors(int report_level, CountTypes boosting_mode,
|
||||
const FontInfoTable& fontinfo_table,
|
||||
|
@ -161,7 +161,7 @@ CHAR_DESC NewCharDescription(const FEATURE_DEFS_STRUCT &FeatureDefs) {
|
||||
CharDesc->NumFeatureSets = FeatureDefs.NumFeatureTypes;
|
||||
|
||||
for (size_t i = 0; i < CharDesc->NumFeatureSets; i++)
|
||||
CharDesc->FeatureSets[i] = NULL;
|
||||
CharDesc->FeatureSets[i] = nullptr;
|
||||
|
||||
return (CharDesc);
|
||||
|
||||
|
@ -24,8 +24,8 @@ namespace tesseract {
|
||||
|
||||
IntFeatureDist::IntFeatureDist()
|
||||
: size_(0), total_feature_weight_(0.0),
|
||||
feature_map_(NULL), features_(NULL),
|
||||
features_delta_one_(NULL), features_delta_two_(NULL) {
|
||||
feature_map_(nullptr), features_(nullptr),
|
||||
features_delta_one_(nullptr), features_delta_two_(nullptr) {
|
||||
}
|
||||
|
||||
IntFeatureDist::~IntFeatureDist() {
|
||||
@ -149,11 +149,11 @@ double IntFeatureDist::DebugFeatureDistance(
|
||||
// Clear all data.
|
||||
void IntFeatureDist::Clear() {
|
||||
delete [] features_;
|
||||
features_ = NULL;
|
||||
features_ = nullptr;
|
||||
delete [] features_delta_one_;
|
||||
features_delta_one_ = NULL;
|
||||
features_delta_one_ = nullptr;
|
||||
delete [] features_delta_two_;
|
||||
features_delta_two_ = NULL;
|
||||
features_delta_two_ = nullptr;
|
||||
}
|
||||
|
||||
} // namespace tesseract
|
||||
|
@ -34,8 +34,8 @@ const int kMaxOffsetDist = 32;
|
||||
IntFeatureMap::IntFeatureMap()
|
||||
: mapping_changed_(true), compact_size_(0) {
|
||||
for (int dir = 0; dir < kNumOffsetMaps; ++dir) {
|
||||
offset_plus_[dir] = NULL;
|
||||
offset_minus_[dir] = NULL;
|
||||
offset_plus_[dir] = nullptr;
|
||||
offset_minus_[dir] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,8 +181,8 @@ void IntFeatureMap::Clear() {
|
||||
for (int dir = 0; dir < kNumOffsetMaps; ++dir) {
|
||||
delete [] offset_plus_[dir];
|
||||
delete [] offset_minus_[dir];
|
||||
offset_plus_[dir] = NULL;
|
||||
offset_minus_[dir] = NULL;
|
||||
offset_plus_[dir] = nullptr;
|
||||
offset_minus_[dir] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,16 +83,16 @@ TrainingSample* BlobToTrainingSample(
|
||||
GenericVector<INT_FEATURE_STRUCT>* bl_features) {
|
||||
GenericVector<INT_FEATURE_STRUCT> cn_features;
|
||||
Classify::ExtractFeatures(blob, nonlinear_norm, bl_features,
|
||||
&cn_features, fx_info, NULL);
|
||||
&cn_features, fx_info, nullptr);
|
||||
// TODO(rays) Use blob->PreciseBoundingBox() instead.
|
||||
TBOX box = blob.bounding_box();
|
||||
TrainingSample* sample = NULL;
|
||||
TrainingSample* sample = nullptr;
|
||||
int num_features = fx_info->NumCN;
|
||||
if (num_features > 0) {
|
||||
sample = TrainingSample::CopyFromFeatures(*fx_info, box, &cn_features[0],
|
||||
num_features);
|
||||
}
|
||||
if (sample != NULL) {
|
||||
if (sample != nullptr) {
|
||||
// Set the bounding box (in original image coordinates) in the sample.
|
||||
TPOINT topleft, botright;
|
||||
topleft.x = box.left();
|
||||
@ -100,8 +100,8 @@ TrainingSample* BlobToTrainingSample(
|
||||
botright.x = box.right();
|
||||
botright.y = box.bottom();
|
||||
TPOINT original_topleft, original_botright;
|
||||
blob.denorm().DenormTransform(NULL, topleft, &original_topleft);
|
||||
blob.denorm().DenormTransform(NULL, botright, &original_botright);
|
||||
blob.denorm().DenormTransform(nullptr, topleft, &original_topleft);
|
||||
blob.denorm().DenormTransform(nullptr, botright, &original_botright);
|
||||
sample->set_bounding_box(TBOX(original_topleft.x, original_botright.y,
|
||||
original_botright.x, original_topleft.y));
|
||||
}
|
||||
@ -136,7 +136,7 @@ void Classify::SetupBLCNDenorms(const TBLOB& blob, bool nonlinear_norm,
|
||||
// Compute 1st and 2nd moments of the original outline.
|
||||
FCOORD center, second_moments;
|
||||
int length = blob.ComputeMoments(¢er, &second_moments);
|
||||
if (fx_info != NULL) {
|
||||
if (fx_info != nullptr) {
|
||||
fx_info->Length = length;
|
||||
fx_info->Rx = IntCastRounded(second_moments.y());
|
||||
fx_info->Ry = IntCastRounded(second_moments.x());
|
||||
@ -145,7 +145,7 @@ void Classify::SetupBLCNDenorms(const TBLOB& blob, bool nonlinear_norm,
|
||||
fx_info->Ymean = IntCastRounded(center.y());
|
||||
}
|
||||
// Setup the denorm for Baseline normalization.
|
||||
bl_denorm->SetupNormalization(NULL, NULL, &blob.denorm(), center.x(), 128.0f,
|
||||
bl_denorm->SetupNormalization(nullptr, nullptr, &blob.denorm(), center.x(), 128.0f,
|
||||
1.0f, 1.0f, 128.0f, 128.0f);
|
||||
// Setup the denorm for character normalization.
|
||||
if (nonlinear_norm) {
|
||||
@ -158,7 +158,7 @@ void Classify::SetupBLCNDenorms(const TBLOB& blob, bool nonlinear_norm,
|
||||
cn_denorm->SetupNonLinear(&blob.denorm(), box, UINT8_MAX, UINT8_MAX,
|
||||
0.0f, 0.0f, x_coords, y_coords);
|
||||
} else {
|
||||
cn_denorm->SetupNormalization(NULL, NULL, &blob.denorm(),
|
||||
cn_denorm->SetupNormalization(nullptr, nullptr, &blob.denorm(),
|
||||
center.x(), center.y(),
|
||||
51.2f / second_moments.x(),
|
||||
51.2f / second_moments.y(),
|
||||
@ -322,7 +322,7 @@ static int GatherPoints(const C_OUTLINE* outline, double feature_length,
|
||||
|
||||
// Extracts Tesseract features and appends them to the features vector.
|
||||
// Startpt to lastpt, inclusive, MUST have the same src_outline member,
|
||||
// which may be NULL. The vector from lastpt to its next is included in
|
||||
// which may be nullptr. The vector from lastpt to its next is included in
|
||||
// the feature extraction. Hidden edges should be excluded by the caller.
|
||||
// If force_poly is true, the features will be extracted from the polygonal
|
||||
// approximation even if more accurate data is available.
|
||||
@ -332,7 +332,7 @@ static void ExtractFeaturesFromRun(
|
||||
GenericVector<INT_FEATURE_STRUCT>* features) {
|
||||
const EDGEPT* endpt = lastpt->next;
|
||||
const C_OUTLINE* outline = startpt->src_outline;
|
||||
if (outline != NULL && !force_poly) {
|
||||
if (outline != nullptr && !force_poly) {
|
||||
// Detailed information is available. We have to normalize only from
|
||||
// the root_denorm to denorm.
|
||||
const DENORM* root_denorm = denorm.RootDenorm();
|
||||
@ -438,7 +438,7 @@ static void ExtractFeaturesFromRun(
|
||||
// (x,y) position and angle as measured counterclockwise from the vector
|
||||
// <-1, 0>, from blob using two normalizations defined by bl_denorm and
|
||||
// cn_denorm. See SetpuBLCNDenorms for definitions.
|
||||
// If outline_cn_counts is not NULL, on return it contains the cumulative
|
||||
// If outline_cn_counts is not nullptr, on return it contains the cumulative
|
||||
// number of cn features generated for each outline in the blob (in order).
|
||||
// Thus after the first outline, there were (*outline_cn_counts)[0] features,
|
||||
// after the second outline, there were (*outline_cn_counts)[1] features etc.
|
||||
@ -451,14 +451,14 @@ void Classify::ExtractFeatures(const TBLOB& blob,
|
||||
DENORM bl_denorm, cn_denorm;
|
||||
tesseract::Classify::SetupBLCNDenorms(blob, nonlinear_norm,
|
||||
&bl_denorm, &cn_denorm, results);
|
||||
if (outline_cn_counts != NULL)
|
||||
if (outline_cn_counts != nullptr)
|
||||
outline_cn_counts->truncate(0);
|
||||
// Iterate the outlines.
|
||||
for (TESSLINE* ol = blob.outlines; ol != NULL; ol = ol->next) {
|
||||
for (TESSLINE* ol = blob.outlines; ol != nullptr; ol = ol->next) {
|
||||
// Iterate the polygon.
|
||||
EDGEPT* loop_pt = ol->FindBestStartPt();
|
||||
EDGEPT* pt = loop_pt;
|
||||
if (pt == NULL) continue;
|
||||
if (pt == nullptr) continue;
|
||||
do {
|
||||
if (pt->IsHidden()) continue;
|
||||
// Find a run of equal src_outline.
|
||||
@ -476,7 +476,7 @@ void Classify::ExtractFeatures(const TBLOB& blob,
|
||||
false, cn_features);
|
||||
pt = last_pt;
|
||||
} while ((pt = pt->next) != loop_pt);
|
||||
if (outline_cn_counts != NULL)
|
||||
if (outline_cn_counts != nullptr)
|
||||
outline_cn_counts->push_back(cn_features->size());
|
||||
}
|
||||
results->NumBL = bl_features->size();
|
||||
|
@ -422,14 +422,14 @@ int Classify::PruneClasses(const INT_TEMPLATES_STRUCT* int_templates,
|
||||
pruner.AdjustForExpectedNumFeatures(expected_num_features,
|
||||
classify_cp_cutoff_strength);
|
||||
// Apply disabled classes in unicharset - only works without a shape_table.
|
||||
if (shape_table_ == NULL)
|
||||
if (shape_table_ == nullptr)
|
||||
pruner.DisableDisabledClasses(unicharset);
|
||||
// If fragments are disabled, remove them, also only without a shape table.
|
||||
if (disable_character_fragments && shape_table_ == NULL)
|
||||
if (disable_character_fragments && shape_table_ == nullptr)
|
||||
pruner.DisableFragments(unicharset);
|
||||
|
||||
// If we have good x-heights, apply the given normalization factors.
|
||||
if (normalization_factors != NULL) {
|
||||
if (normalization_factors != nullptr) {
|
||||
pruner.NormalizeForXheight(classify_class_pruner_multiplier,
|
||||
normalization_factors);
|
||||
} else {
|
||||
@ -437,7 +437,7 @@ int Classify::PruneClasses(const INT_TEMPLATES_STRUCT* int_templates,
|
||||
}
|
||||
// Do the actual pruning and sort the short-list.
|
||||
pruner.PruneAndSort(classify_class_pruner_threshold, keep_this,
|
||||
shape_table_ == NULL, unicharset);
|
||||
shape_table_ == nullptr, unicharset);
|
||||
|
||||
if (classify_debug_level > 2) {
|
||||
pruner.DebugMatch(*this, int_templates, features);
|
||||
|
@ -176,9 +176,9 @@ int TruncateParam(FLOAT32 Param, int Min, int Max, char *Id);
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
/* global display lists used to display proto and feature match information*/
|
||||
ScrollView *IntMatchWindow = NULL;
|
||||
ScrollView *FeatureDisplayWindow = NULL;
|
||||
ScrollView *ProtoDisplayWindow = NULL;
|
||||
ScrollView *IntMatchWindow = nullptr;
|
||||
ScrollView *FeatureDisplayWindow = nullptr;
|
||||
ScrollView *ProtoDisplayWindow = nullptr;
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
Variables
|
||||
@ -465,7 +465,7 @@ uint8_t CircBucketFor(FLOAT32 param, FLOAT32 offset, int num_buckets) {
|
||||
* @note History: Thu Mar 21 15:40:19 1991, DSJ, Created.
|
||||
*/
|
||||
void UpdateMatchDisplay() {
|
||||
if (IntMatchWindow != NULL)
|
||||
if (IntMatchWindow != nullptr)
|
||||
IntMatchWindow->Update();
|
||||
} /* ClearMatchDisplay */
|
||||
#endif
|
||||
@ -522,13 +522,13 @@ void Classify::ConvertProto(PROTO Proto, int ProtoId, INT_CLASS Class) {
|
||||
P = ProtoForProtoId(Class, ProtoId);
|
||||
|
||||
Param = Proto->A * 128;
|
||||
P->A = TruncateParam(Param, -128, 127, NULL);
|
||||
P->A = TruncateParam(Param, -128, 127, nullptr);
|
||||
|
||||
Param = -Proto->B * 256;
|
||||
P->B = TruncateParam(Param, 0, 255, NULL);
|
||||
P->B = TruncateParam(Param, 0, 255, nullptr);
|
||||
|
||||
Param = Proto->C * 128;
|
||||
P->C = TruncateParam(Param, -128, 127, NULL);
|
||||
P->C = TruncateParam(Param, -128, 127, nullptr);
|
||||
|
||||
Param = Proto->Angle * 256;
|
||||
if (Param < 0 || Param >= 256)
|
||||
@ -538,7 +538,7 @@ void Classify::ConvertProto(PROTO Proto, int ProtoId, INT_CLASS Class) {
|
||||
|
||||
/* round proto length to nearest integer number of pico-features */
|
||||
Param = (Proto->Length / GetPicoFeatureLength()) + 0.5;
|
||||
Class->ProtoLengths[ProtoId] = TruncateParam(Param, 1, 255, NULL);
|
||||
Class->ProtoLengths[ProtoId] = TruncateParam(Param, 1, 255, nullptr);
|
||||
if (classify_learning_debug_level >= 2)
|
||||
cprintf("Converted ffeat to (A=%d,B=%d,C=%d,L=%d)",
|
||||
P->A, P->B, P->C, Class->ProtoLengths[ProtoId]);
|
||||
@ -691,7 +691,7 @@ INT_CLASS NewIntClass(int MaxNumProtos, int MaxNumConfigs) {
|
||||
memset(Class->ProtoLengths, 0,
|
||||
MaxNumIntProtosIn(Class) * sizeof(*Class->ProtoLengths));
|
||||
} else {
|
||||
Class->ProtoLengths = NULL;
|
||||
Class->ProtoLengths = nullptr;
|
||||
}
|
||||
memset(Class->ConfigLengths, 0, sizeof(Class->ConfigLengths));
|
||||
|
||||
@ -706,7 +706,7 @@ void free_int_class(INT_CLASS int_class) {
|
||||
for (i = 0; i < int_class->NumProtoSets; i++) {
|
||||
Efree (int_class->ProtoSets[i]);
|
||||
}
|
||||
if (int_class->ProtoLengths != NULL) {
|
||||
if (int_class->ProtoLengths != nullptr) {
|
||||
Efree (int_class->ProtoLengths);
|
||||
}
|
||||
Efree(int_class);
|
||||
@ -729,7 +729,7 @@ INT_TEMPLATES NewIntTemplates() {
|
||||
T->NumClassPruners = 0;
|
||||
|
||||
for (i = 0; i < MAX_NUM_CLASSES; i++)
|
||||
ClassForClassId (T, i) = NULL;
|
||||
ClassForClassId (T, i) = nullptr;
|
||||
|
||||
return (T);
|
||||
} /* NewIntTemplates */
|
||||
@ -912,7 +912,7 @@ INT_TEMPLATES Classify::ReadIntTemplates(TFile *fp) {
|
||||
}
|
||||
|
||||
/* then read in the proto lengths */
|
||||
Lengths = NULL;
|
||||
Lengths = nullptr;
|
||||
if (MaxNumIntProtosIn (Class) > 0) {
|
||||
Lengths = (uint8_t *)Emalloc(sizeof(uint8_t) * MaxNumIntProtosIn(Class));
|
||||
if (fp->FRead(Lengths, sizeof(uint8_t), MaxNumIntProtosIn(Class)) !=
|
||||
@ -954,7 +954,7 @@ INT_TEMPLATES Classify::ReadIntTemplates(TFile *fp) {
|
||||
}
|
||||
|
||||
if (version_id < 2) {
|
||||
/* add an empty NULL class with class id 0 */
|
||||
/* add an empty nullptr class with class id 0 */
|
||||
assert(UnusedClassIdIn (Templates, 0));
|
||||
ClassForClassId (Templates, 0) = NewIntClass (1, 1);
|
||||
ClassForClassId (Templates, 0)->font_set_id = -1;
|
||||
@ -962,12 +962,12 @@ INT_TEMPLATES Classify::ReadIntTemplates(TFile *fp) {
|
||||
/* make sure the classes are contiguous */
|
||||
for (i = 0; i < MAX_NUM_CLASSES; i++) {
|
||||
if (i < Templates->NumClasses) {
|
||||
if (ClassForClassId (Templates, i) == NULL) {
|
||||
if (ClassForClassId (Templates, i) == nullptr) {
|
||||
fprintf(stderr, "Non-contiguous class ids in inttemp\n");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if (ClassForClassId (Templates, i) != NULL) {
|
||||
if (ClassForClassId (Templates, i) != nullptr) {
|
||||
fprintf(stderr, "Class id %d exceeds NumClassesIn (Templates) %d\n",
|
||||
i, Templates->NumClasses);
|
||||
exit(1);
|
||||
@ -1338,7 +1338,7 @@ CLASS_ID Classify::GetClassToDebug(const char *Prompt, bool* adaptive_on,
|
||||
ev_type = ev->type;
|
||||
if (ev_type == SVET_POPUP) {
|
||||
if (ev->command_id == IDA_SHAPE_INDEX) {
|
||||
if (shape_table_ != NULL) {
|
||||
if (shape_table_ != nullptr) {
|
||||
*shape_id = atoi(ev->parameter);
|
||||
*adaptive_on = false;
|
||||
*pretrained_on = true;
|
||||
@ -1368,7 +1368,7 @@ CLASS_ID Classify::GetClassToDebug(const char *Prompt, bool* adaptive_on,
|
||||
*adaptive_on = true;
|
||||
*pretrained_on = true;
|
||||
}
|
||||
if (ev->command_id == IDA_ADAPTIVE || shape_table_ == NULL) {
|
||||
if (ev->command_id == IDA_ADAPTIVE || shape_table_ == nullptr) {
|
||||
*shape_id = -1;
|
||||
return unichar_id;
|
||||
}
|
||||
@ -1695,7 +1695,7 @@ void RenderIntFeature(ScrollView *window, const INT_FEATURE_STRUCT* Feature,
|
||||
FLOAT32 X, Y, Dx, Dy, Length;
|
||||
|
||||
window->Pen(color);
|
||||
assert(Feature != NULL);
|
||||
assert(Feature != nullptr);
|
||||
assert(color != 0);
|
||||
|
||||
X = Feature->X;
|
||||
@ -1741,7 +1741,7 @@ void RenderIntProto(ScrollView *window,
|
||||
int Bucket;
|
||||
|
||||
assert(ProtoId >= 0);
|
||||
assert(Class != NULL);
|
||||
assert(Class != nullptr);
|
||||
assert(ProtoId < Class->NumProtos);
|
||||
assert(color != 0);
|
||||
window->Pen(color);
|
||||
@ -1815,7 +1815,7 @@ int TruncateParam(FLOAT32 Param, int Min, int Max, char *Id) {
|
||||
* initialized.
|
||||
*/
|
||||
void InitIntMatchWindowIfReqd() {
|
||||
if (IntMatchWindow == NULL) {
|
||||
if (IntMatchWindow == nullptr) {
|
||||
IntMatchWindow = CreateFeatureSpaceWindow("IntMatchWindow", 50, 200);
|
||||
SVMenuNode* popup_menu = new SVMenuNode();
|
||||
|
||||
@ -1836,7 +1836,7 @@ void InitIntMatchWindowIfReqd() {
|
||||
* initialized.
|
||||
*/
|
||||
void InitProtoDisplayWindowIfReqd() {
|
||||
if (ProtoDisplayWindow == NULL) {
|
||||
if (ProtoDisplayWindow == nullptr) {
|
||||
ProtoDisplayWindow = CreateFeatureSpaceWindow("ProtoDisplayWindow",
|
||||
550, 200);
|
||||
}
|
||||
@ -1847,7 +1847,7 @@ void InitProtoDisplayWindowIfReqd() {
|
||||
* initialized.
|
||||
*/
|
||||
void InitFeatureDisplayWindowIfReqd() {
|
||||
if (FeatureDisplayWindow == NULL) {
|
||||
if (FeatureDisplayWindow == nullptr) {
|
||||
FeatureDisplayWindow = CreateFeatureSpaceWindow("FeatureDisplayWindow",
|
||||
50, 700);
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ enum IntmatcherDebugAction {
|
||||
|
||||
#define MaxNumClassesIn(T) (T->NumClassPruners * CLASSES_PER_CP)
|
||||
#define LegalClassId(c) ((c) >= 0 && (c) <= MAX_CLASS_ID)
|
||||
#define UnusedClassIdIn(T,c) ((T)->Class[c] == NULL)
|
||||
#define UnusedClassIdIn(T,c) ((T)->Class[c] == nullptr)
|
||||
#define ClassForClassId(T,c) ((T)->Class[c])
|
||||
#define ClassPrunersFor(T) ((T)->ClassPruner)
|
||||
#define CPrunerIdFor(c) ((c) / CLASSES_PER_CP)
|
||||
|
@ -153,7 +153,7 @@ KDTreeSearch::~KDTreeSearch() {
|
||||
void KDTreeSearch::Search(int *result_count,
|
||||
FLOAT32 *distances,
|
||||
void **results) {
|
||||
if (tree_->Root.Left == NULL) {
|
||||
if (tree_->Root.Left == nullptr) {
|
||||
*result_count = 0;
|
||||
} else {
|
||||
for (int i = 0; i < tree_->KeySize; i++) {
|
||||
@ -196,8 +196,8 @@ KDTREE *MakeKDTree(int16_t KeySize, const PARAM_DESC KeyDesc[]) {
|
||||
}
|
||||
}
|
||||
KDTree->KeySize = KeySize;
|
||||
KDTree->Root.Left = NULL;
|
||||
KDTree->Root.Right = NULL;
|
||||
KDTree->Root.Left = nullptr;
|
||||
KDTree->Root.Right = nullptr;
|
||||
return KDTree;
|
||||
}
|
||||
|
||||
@ -222,7 +222,7 @@ void KDStore(KDTREE *Tree, FLOAT32 *Key, void *Data) {
|
||||
PtrToNode = &(Tree->Root.Left);
|
||||
Node = *PtrToNode;
|
||||
Level = NextLevel(Tree, -1);
|
||||
while (Node != NULL) {
|
||||
while (Node != nullptr) {
|
||||
if (Key[Level] < Node->BranchPoint) {
|
||||
PtrToNode = &(Node->Left);
|
||||
if (Key[Level] > Node->LeftBranch)
|
||||
@ -271,7 +271,7 @@ KDDelete (KDTREE * Tree, FLOAT32 Key[], void *Data) {
|
||||
Level = NextLevel(Tree, -1);
|
||||
|
||||
/* search tree for node to be deleted */
|
||||
while ((Current != NULL) && (!NodeFound (Current, Key, Data))) {
|
||||
while ((Current != nullptr) && (!NodeFound (Current, Key, Data))) {
|
||||
Father = Current;
|
||||
if (Key[Level] < Current->BranchPoint)
|
||||
Current = Current->Left;
|
||||
@ -281,12 +281,12 @@ KDDelete (KDTREE * Tree, FLOAT32 Key[], void *Data) {
|
||||
Level = NextLevel(Tree, Level);
|
||||
}
|
||||
|
||||
if (Current != NULL) { /* if node to be deleted was found */
|
||||
if (Current != nullptr) { /* if node to be deleted was found */
|
||||
if (Current == Father->Left) {
|
||||
Father->Left = NULL;
|
||||
Father->Left = nullptr;
|
||||
Father->LeftBranch = Tree->KeyDesc[Level].Min;
|
||||
} else {
|
||||
Father->Right = NULL;
|
||||
Father->Right = nullptr;
|
||||
Father->RightBranch = Tree->KeyDesc[Level].Max;
|
||||
}
|
||||
|
||||
@ -327,7 +327,7 @@ void KDNearestNeighborSearch(
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** Walk a given Tree with action. */
|
||||
void KDWalk(KDTREE *Tree, void_proc action, void *context) {
|
||||
if (Tree->Root.Left != NULL)
|
||||
if (Tree->Root.Left != nullptr)
|
||||
Walk(Tree, action, context, Tree->Root.Left, NextLevel(Tree, -1));
|
||||
}
|
||||
|
||||
@ -378,8 +378,8 @@ KDNODE *MakeKDNode(KDTREE *tree, FLOAT32 Key[], void *Data, int Index) {
|
||||
NewNode->BranchPoint = Key[Index];
|
||||
NewNode->LeftBranch = tree->KeyDesc[Index].Min;
|
||||
NewNode->RightBranch = tree->KeyDesc[Index].Max;
|
||||
NewNode->Left = NULL;
|
||||
NewNode->Right = NULL;
|
||||
NewNode->Left = nullptr;
|
||||
NewNode->Right = nullptr;
|
||||
|
||||
return NewNode;
|
||||
} /* MakeKDNode */
|
||||
@ -406,26 +406,26 @@ void KDTreeSearch::SearchRec(int level, KDNODE *sub_tree) {
|
||||
sub_tree->Data);
|
||||
|
||||
if (query_point_[level] < sub_tree->BranchPoint) {
|
||||
if (sub_tree->Left != NULL) {
|
||||
if (sub_tree->Left != nullptr) {
|
||||
FLOAT32 tmp = sb_max_[level];
|
||||
sb_max_[level] = sub_tree->LeftBranch;
|
||||
SearchRec(NextLevel(tree_, level), sub_tree->Left);
|
||||
sb_max_[level] = tmp;
|
||||
}
|
||||
if (sub_tree->Right != NULL) {
|
||||
if (sub_tree->Right != nullptr) {
|
||||
FLOAT32 tmp = sb_min_[level];
|
||||
sb_min_[level] = sub_tree->RightBranch;
|
||||
SearchRec(NextLevel(tree_, level), sub_tree->Right);
|
||||
sb_min_[level] = tmp;
|
||||
}
|
||||
} else {
|
||||
if (sub_tree->Right != NULL) {
|
||||
if (sub_tree->Right != nullptr) {
|
||||
FLOAT32 tmp = sb_min_[level];
|
||||
sb_min_[level] = sub_tree->RightBranch;
|
||||
SearchRec(NextLevel(tree_, level), sub_tree->Right);
|
||||
sb_min_[level] = tmp;
|
||||
}
|
||||
if (sub_tree->Left != NULL) {
|
||||
if (sub_tree->Left != nullptr) {
|
||||
FLOAT32 tmp = sb_max_[level];
|
||||
sb_max_[level] = sub_tree->LeftBranch;
|
||||
SearchRec(NextLevel(tree_, level), sub_tree->Left);
|
||||
@ -530,15 +530,15 @@ bool KDTreeSearch::BoxIntersectsSearch(FLOAT32 *lower, FLOAT32 *upper) {
|
||||
void Walk(KDTREE *tree, void_proc action, void *context,
|
||||
KDNODE *sub_tree, int32_t level) {
|
||||
(*action)(context, sub_tree->Data, level);
|
||||
if (sub_tree->Left != NULL)
|
||||
if (sub_tree->Left != nullptr)
|
||||
Walk(tree, action, context, sub_tree->Left, NextLevel(tree, level));
|
||||
if (sub_tree->Right != NULL)
|
||||
if (sub_tree->Right != nullptr)
|
||||
Walk(tree, action, context, sub_tree->Right, NextLevel(tree, level));
|
||||
}
|
||||
|
||||
/** Given a subtree nodes, insert all of its elements into tree. */
|
||||
void InsertNodes(KDTREE *tree, KDNODE *nodes) {
|
||||
if (nodes == NULL)
|
||||
if (nodes == nullptr)
|
||||
return;
|
||||
|
||||
KDStore(tree, nodes->Key, nodes->Data);
|
||||
@ -548,7 +548,7 @@ void InsertNodes(KDTREE *tree, KDNODE *nodes) {
|
||||
|
||||
/** Free all of the nodes of a sub tree. */
|
||||
void FreeSubTree(KDNODE *sub_tree) {
|
||||
if (sub_tree != NULL) {
|
||||
if (sub_tree != nullptr) {
|
||||
FreeSubTree(sub_tree->Left);
|
||||
FreeSubTree(sub_tree->Right);
|
||||
free(sub_tree);
|
||||
|
@ -60,7 +60,7 @@ MasterTrainer::MasterTrainer(NormalizationMode norm_mode,
|
||||
charsetsize_(0),
|
||||
enable_shape_anaylsis_(shape_analysis),
|
||||
enable_replication_(replicate_samples),
|
||||
fragments_(NULL), prev_unichar_id_(-1), debug_level_(debug_level) {
|
||||
fragments_(nullptr), prev_unichar_id_(-1), debug_level_(debug_level) {
|
||||
}
|
||||
|
||||
MasterTrainer::~MasterTrainer() {
|
||||
@ -122,17 +122,17 @@ void MasterTrainer::ReadTrainingSamples(const char* page_name,
|
||||
int geo_feature_type = ShortNameToFeatureType(feature_defs, kGeoFeatureType);
|
||||
|
||||
FILE* fp = Efopen(page_name, "rb");
|
||||
if (fp == NULL) {
|
||||
if (fp == nullptr) {
|
||||
tprintf("Failed to open tr file: %s\n", page_name);
|
||||
return;
|
||||
}
|
||||
tr_filenames_.push_back(STRING(page_name));
|
||||
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
||||
while (fgets(buffer, sizeof(buffer), fp) != nullptr) {
|
||||
if (buffer[0] == '\n')
|
||||
continue;
|
||||
|
||||
char* space = strchr(buffer, ' ');
|
||||
if (space == NULL) {
|
||||
if (space == nullptr) {
|
||||
tprintf("Bad format in tr file, reading fontname, unichar\n");
|
||||
continue;
|
||||
}
|
||||
@ -177,7 +177,7 @@ void MasterTrainer::AddSample(bool verification, const char* unichar,
|
||||
int junk_id = junk_samples_.AddSample(unichar, sample);
|
||||
if (prev_unichar_id_ >= 0) {
|
||||
CHAR_FRAGMENT* frag = CHAR_FRAGMENT::parse_from_string(unichar);
|
||||
if (frag != NULL && frag->is_natural()) {
|
||||
if (frag != nullptr && frag->is_natural()) {
|
||||
if (fragments_[prev_unichar_id_] == 0)
|
||||
fragments_[prev_unichar_id_] = junk_id;
|
||||
else if (fragments_[prev_unichar_id_] != junk_id)
|
||||
@ -216,7 +216,7 @@ void MasterTrainer::PostLoadCleanup() {
|
||||
if (enable_shape_anaylsis_)
|
||||
ReplaceFragmentedSamples();
|
||||
SampleIterator sample_it;
|
||||
sample_it.Init(NULL, NULL, true, &verify_samples_);
|
||||
sample_it.Init(nullptr, nullptr, true, &verify_samples_);
|
||||
sample_it.NormalizeSamples();
|
||||
verify_samples_.OrganizeByFontAndClass();
|
||||
|
||||
@ -262,24 +262,24 @@ void MasterTrainer::SetupMasterShapes() {
|
||||
|
||||
const CHAR_FRAGMENT *fragment = samples_.unicharset().get_fragment(c);
|
||||
|
||||
if (fragment == NULL)
|
||||
char_shapes.AppendMasterShapes(shapes, NULL);
|
||||
if (fragment == nullptr)
|
||||
char_shapes.AppendMasterShapes(shapes, nullptr);
|
||||
else if (fragment->is_beginning())
|
||||
char_shapes_begin_fragment.AppendMasterShapes(shapes, NULL);
|
||||
char_shapes_begin_fragment.AppendMasterShapes(shapes, nullptr);
|
||||
else if (fragment->is_ending())
|
||||
char_shapes_end_fragment.AppendMasterShapes(shapes, NULL);
|
||||
char_shapes_end_fragment.AppendMasterShapes(shapes, nullptr);
|
||||
else
|
||||
char_shapes.AppendMasterShapes(shapes, NULL);
|
||||
char_shapes.AppendMasterShapes(shapes, nullptr);
|
||||
}
|
||||
ClusterShapes(kMinClusteredShapes, kMaxUnicharsPerCluster,
|
||||
kFontMergeDistance, &char_shapes_begin_fragment);
|
||||
char_shapes.AppendMasterShapes(char_shapes_begin_fragment, NULL);
|
||||
char_shapes.AppendMasterShapes(char_shapes_begin_fragment, nullptr);
|
||||
ClusterShapes(kMinClusteredShapes, kMaxUnicharsPerCluster,
|
||||
kFontMergeDistance, &char_shapes_end_fragment);
|
||||
char_shapes.AppendMasterShapes(char_shapes_end_fragment, NULL);
|
||||
char_shapes.AppendMasterShapes(char_shapes_end_fragment, nullptr);
|
||||
ClusterShapes(kMinClusteredShapes, kMaxUnicharsPerCluster,
|
||||
kFontMergeDistance, &char_shapes);
|
||||
master_shapes_.AppendMasterShapes(char_shapes, NULL);
|
||||
master_shapes_.AppendMasterShapes(char_shapes, nullptr);
|
||||
tprintf("Master shape_table:%s\n", master_shapes_.SummaryStr().string());
|
||||
}
|
||||
|
||||
@ -334,7 +334,7 @@ void MasterTrainer::ReplicateAndRandomizeSamplesIfRequired() {
|
||||
// Returns false on failure.
|
||||
bool MasterTrainer::LoadFontInfo(const char* filename) {
|
||||
FILE* fp = fopen(filename, "rb");
|
||||
if (fp == NULL) {
|
||||
if (fp == nullptr) {
|
||||
fprintf(stderr, "Failed to load font_properties from %s\n", filename);
|
||||
return false;
|
||||
}
|
||||
@ -371,9 +371,9 @@ bool MasterTrainer::LoadFontInfo(const char* filename) {
|
||||
bool MasterTrainer::LoadXHeights(const char* filename) {
|
||||
tprintf("fontinfo table is of size %d\n", fontinfo_table_.size());
|
||||
xheights_.init_to_size(fontinfo_table_.size(), -1);
|
||||
if (filename == NULL) return true;
|
||||
if (filename == nullptr) return true;
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if (f == NULL) {
|
||||
if (f == nullptr) {
|
||||
fprintf(stderr, "Failed to load font xheights from %s\n", filename);
|
||||
return false;
|
||||
}
|
||||
@ -413,7 +413,7 @@ bool MasterTrainer::LoadXHeights(const char* filename) {
|
||||
// Reads spacing stats from filename and adds them to fontinfo_table.
|
||||
bool MasterTrainer::AddSpacingInfo(const char *filename) {
|
||||
FILE* fontinfo_file = fopen(filename, "rb");
|
||||
if (fontinfo_file == NULL)
|
||||
if (fontinfo_file == nullptr)
|
||||
return true; // We silently ignore missing files!
|
||||
// Find the fontinfo_id.
|
||||
int fontinfo_id = GetBestMatchingFontInfoId(filename);
|
||||
@ -433,7 +433,7 @@ bool MasterTrainer::AddSpacingInfo(const char *filename) {
|
||||
ASSERT_HOST(tfscanf(fontinfo_file, "%d\n", &num_unichars) == 1);
|
||||
FontInfo *fi = &fontinfo_table_.get(fontinfo_id);
|
||||
fi->init_spacing(unicharset_.size());
|
||||
FontSpacingInfo *spacing = NULL;
|
||||
FontSpacingInfo *spacing = nullptr;
|
||||
for (int l = 0; l < num_unichars; ++l) {
|
||||
if (tfscanf(fontinfo_file, "%s %d %d %d",
|
||||
uch, &x_gap_before, &x_gap_after, &num_kerned) != 4) {
|
||||
@ -482,7 +482,7 @@ int MasterTrainer::GetBestMatchingFontInfoId(const char* filename) {
|
||||
int fontinfo_id = -1;
|
||||
int best_len = 0;
|
||||
for (int f = 0; f < fontinfo_table_.size(); ++f) {
|
||||
if (strstr(filename, fontinfo_table_.get(f).name) != NULL) {
|
||||
if (strstr(filename, fontinfo_table_.get(f).name) != nullptr) {
|
||||
int len = strlen(fontinfo_table_.get(f).name);
|
||||
// Use the longest matching length in case a substring of a font matched.
|
||||
if (len > best_len) {
|
||||
@ -744,7 +744,7 @@ void MasterTrainer::TestClassifierVOld(bool replicate_samples,
|
||||
ShapeClassifier* test_classifier,
|
||||
ShapeClassifier* old_classifier) {
|
||||
SampleIterator sample_it;
|
||||
sample_it.Init(NULL, NULL, replicate_samples, &samples_);
|
||||
sample_it.Init(nullptr, nullptr, replicate_samples, &samples_);
|
||||
ErrorCounter::DebugNewErrors(test_classifier, old_classifier,
|
||||
CT_UNICHAR_TOPN_ERR, fontinfo_table_,
|
||||
page_images_, &sample_it);
|
||||
@ -772,7 +772,7 @@ void MasterTrainer::TestClassifierOnSamples(CountTypes error_mode,
|
||||
// 5 = list of all errors + short classifier debug output on 25 errors.
|
||||
// If replicate_samples is true, then the test is run on an extended test
|
||||
// sample including replicated and systematically perturbed samples.
|
||||
// If report_string is non-NULL, a summary of the results for each font
|
||||
// If report_string is non-nullptr, a summary of the results for each font
|
||||
// is appended to the report_string.
|
||||
double MasterTrainer::TestClassifier(CountTypes error_mode,
|
||||
int report_level,
|
||||
@ -781,7 +781,7 @@ double MasterTrainer::TestClassifier(CountTypes error_mode,
|
||||
ShapeClassifier* test_classifier,
|
||||
STRING* report_string) {
|
||||
SampleIterator sample_it;
|
||||
sample_it.Init(NULL, NULL, replicate_samples, samples);
|
||||
sample_it.Init(nullptr, nullptr, replicate_samples, samples);
|
||||
if (report_level > 0) {
|
||||
int num_samples = 0;
|
||||
for (sample_it.Begin(); !sample_it.AtEnd(); sample_it.Next())
|
||||
@ -795,7 +795,7 @@ double MasterTrainer::TestClassifier(CountTypes error_mode,
|
||||
ErrorCounter::ComputeErrorRate(test_classifier, report_level,
|
||||
error_mode, fontinfo_table_,
|
||||
page_images_, &sample_it, &unichar_error,
|
||||
NULL, report_string);
|
||||
nullptr, report_string);
|
||||
return unichar_error;
|
||||
}
|
||||
|
||||
@ -832,7 +832,7 @@ float MasterTrainer::ShapeDistance(const ShapeTable& shapes, int s1, int s2) {
|
||||
// Replaces samples that are always fragmented with the corresponding
|
||||
// fragment samples.
|
||||
void MasterTrainer::ReplaceFragmentedSamples() {
|
||||
if (fragments_ == NULL) return;
|
||||
if (fragments_ == nullptr) return;
|
||||
// Remove samples that are replaced by fragments. Each class that was
|
||||
// always naturally fragmented should be replaced by its fragments.
|
||||
int num_samples = samples_.num_samples();
|
||||
@ -875,7 +875,7 @@ void MasterTrainer::ReplaceFragmentedSamples() {
|
||||
int junk_id = sample->class_id();
|
||||
const char* frag_utf8 = frag_set.id_to_unichar(junk_id);
|
||||
CHAR_FRAGMENT* frag = CHAR_FRAGMENT::parse_from_string(frag_utf8);
|
||||
if (frag != NULL && frag->is_natural()) {
|
||||
if (frag != nullptr && frag->is_natural()) {
|
||||
junk_samples_.extract_sample(s);
|
||||
samples_.AddSample(frag_set.id_to_unichar(junk_id), sample);
|
||||
}
|
||||
@ -889,7 +889,7 @@ void MasterTrainer::ReplaceFragmentedSamples() {
|
||||
// delete [] good_junk;
|
||||
// Fragments_ no longer needed?
|
||||
delete [] fragments_;
|
||||
fragments_ = NULL;
|
||||
fragments_ = nullptr;
|
||||
}
|
||||
|
||||
// Runs a hierarchical agglomerative clustering to merge shapes in the given
|
||||
|
@ -233,7 +233,7 @@ class MasterTrainer {
|
||||
// 5 = list of all errors + short classifier debug output on 25 errors.
|
||||
// If replicate_samples is true, then the test is run on an extended test
|
||||
// sample including replicated and systematically perturbed samples.
|
||||
// If report_string is non-NULL, a summary of the results for each font
|
||||
// If report_string is non-nullptr, a summary of the results for each font
|
||||
// is appended to the report_string.
|
||||
double TestClassifier(CountTypes error_mode,
|
||||
int report_level,
|
||||
|
@ -50,8 +50,8 @@ FEATURE_SET ExtractMicros(TBLOB* Blob, const DENORM& cn_denorm) {
|
||||
MICROFEATURE OldFeature;
|
||||
|
||||
OldFeatures = BlobMicroFeatures(Blob, cn_denorm);
|
||||
if (OldFeatures == NULL)
|
||||
return NULL;
|
||||
if (OldFeatures == nullptr)
|
||||
return nullptr;
|
||||
NumFeatures = count (OldFeatures);
|
||||
FeatureSet = NewFeatureSet (NumFeatures);
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
*/
|
||||
LIST ConvertBlob(TBLOB *blob) {
|
||||
LIST outlines = NIL_LIST;
|
||||
return (blob == NULL)
|
||||
return (blob == nullptr)
|
||||
? NIL_LIST
|
||||
: ConvertOutlines(blob->outlines, outlines, outer);
|
||||
}
|
||||
@ -54,7 +54,7 @@ MFOUTLINE ConvertOutline(TESSLINE *outline) {
|
||||
EDGEPT *StartPoint;
|
||||
EDGEPT *NextPoint;
|
||||
|
||||
if (outline == NULL || outline->loop == NULL)
|
||||
if (outline == nullptr || outline->loop == nullptr)
|
||||
return MFOutline;
|
||||
|
||||
StartPoint = outline->loop;
|
||||
@ -75,7 +75,7 @@ MFOUTLINE ConvertOutline(TESSLINE *outline) {
|
||||
EdgePoint = NextPoint;
|
||||
} while (EdgePoint != StartPoint);
|
||||
|
||||
if (MFOutline != NULL)
|
||||
if (MFOutline != nullptr)
|
||||
MakeOutlineCircular(MFOutline);
|
||||
return MFOutline;
|
||||
}
|
||||
@ -94,9 +94,9 @@ LIST ConvertOutlines(TESSLINE *outline,
|
||||
OUTLINETYPE outline_type) {
|
||||
MFOUTLINE mf_outline;
|
||||
|
||||
while (outline != NULL) {
|
||||
while (outline != nullptr) {
|
||||
mf_outline = ConvertOutline(outline);
|
||||
if (mf_outline != NULL)
|
||||
if (mf_outline != nullptr)
|
||||
mf_outlines = push(mf_outlines, mf_outline);
|
||||
outline = outline->next;
|
||||
}
|
||||
@ -159,7 +159,7 @@ void FreeMFOutline(void *arg) { //MFOUTLINE Outline
|
||||
/* break the circular outline so we can use std. techniques to deallocate */
|
||||
Start = list_rest (Outline);
|
||||
set_rest(Outline, NIL_LIST);
|
||||
while (Start != NULL) {
|
||||
while (Start != nullptr) {
|
||||
free(first_node(Start));
|
||||
Start = pop (Start);
|
||||
}
|
||||
@ -466,13 +466,13 @@ MFOUTLINE NextDirectionChange(MFOUTLINE EdgePoint) {
|
||||
|
||||
InitialDirection = PointAt (EdgePoint)->Direction;
|
||||
|
||||
MFOUTLINE next_pt = NULL;
|
||||
MFOUTLINE next_pt = nullptr;
|
||||
do {
|
||||
EdgePoint = NextPointAfter(EdgePoint);
|
||||
next_pt = NextPointAfter(EdgePoint);
|
||||
} while (PointAt(EdgePoint)->Direction == InitialDirection &&
|
||||
!PointAt(EdgePoint)->Hidden &&
|
||||
next_pt != NULL && !PointAt(next_pt)->Hidden);
|
||||
next_pt != nullptr && !PointAt(next_pt)->Hidden);
|
||||
|
||||
return (EdgePoint);
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ MICROFEATURES BlobMicroFeatures(TBLOB* Blob, const DENORM& cn_denorm) {
|
||||
LIST RemainingOutlines;
|
||||
MFOUTLINE Outline;
|
||||
|
||||
if (Blob != NULL) {
|
||||
if (Blob != nullptr) {
|
||||
Outlines = ConvertBlob(Blob);
|
||||
|
||||
RemainingOutlines = Outlines;
|
||||
@ -153,7 +153,7 @@ MICROFEATURES ConvertToMicroFeatures(MFOUTLINE Outline,
|
||||
Current = NextExtremity (Last);
|
||||
if (!PointAt(Current)->Hidden) {
|
||||
NewFeature = ExtractMicroFeature (Last, Current);
|
||||
if (NewFeature != NULL)
|
||||
if (NewFeature != nullptr)
|
||||
MicroFeatures = push (MicroFeatures, NewFeature);
|
||||
}
|
||||
Last = Current;
|
||||
@ -169,11 +169,11 @@ MICROFEATURES ConvertToMicroFeatures(MFOUTLINE Outline,
|
||||
* A new micro-feature is allocated, filled with the feature
|
||||
* parameters, and returned. The routine assumes that
|
||||
* Start and End are not the same point. If they are the
|
||||
* same point, NULL is returned, a warning message is
|
||||
* same point, nullptr is returned, a warning message is
|
||||
* printed, and the current outline is dumped to stdout.
|
||||
* @param Start starting point of micro-feature
|
||||
* @param End ending point of micro-feature
|
||||
* @return New micro-feature or NULL if the feature was rejected.
|
||||
* @return New micro-feature or nullptr if the feature was rejected.
|
||||
* @note Globals: none
|
||||
* @note Exceptions: none
|
||||
* @note History:
|
||||
|
@ -160,13 +160,13 @@ FLOAT32 Classify::ComputeNormMatch(CLASS_ID ClassId,
|
||||
} /* ComputeNormMatch */
|
||||
|
||||
void Classify::FreeNormProtos() {
|
||||
if (NormProtos != NULL) {
|
||||
if (NormProtos != nullptr) {
|
||||
for (int i = 0; i < NormProtos->NumProtos; i++)
|
||||
FreeProtoList(&NormProtos->Protos[i]);
|
||||
Efree(NormProtos->Protos);
|
||||
Efree(NormProtos->ParamDesc);
|
||||
Efree(NormProtos);
|
||||
NormProtos = NULL;
|
||||
NormProtos = nullptr;
|
||||
}
|
||||
}
|
||||
} // namespace tesseract
|
||||
|
@ -52,7 +52,7 @@ FEATURE_SET Classify::ExtractOutlineFeatures(TBLOB *Blob) {
|
||||
FLOAT32 XScale, YScale;
|
||||
|
||||
FeatureSet = NewFeatureSet (MAX_OUTLINE_FEATURES);
|
||||
if (Blob == NULL)
|
||||
if (Blob == nullptr)
|
||||
return (FeatureSet);
|
||||
|
||||
Outlines = ConvertBlob (Blob);
|
||||
|
@ -233,7 +233,7 @@ FEATURE_SET Classify::ExtractIntCNFeatures(
|
||||
GenericVector<INT_FEATURE_STRUCT> bl_features;
|
||||
tesseract::TrainingSample* sample = tesseract::BlobToTrainingSample(
|
||||
blob, false, &local_fx_info, &bl_features);
|
||||
if (sample == NULL) return NULL;
|
||||
if (sample == nullptr) return nullptr;
|
||||
|
||||
int num_features = sample->num_features();
|
||||
const INT_FEATURE_STRUCT* features = sample->features();
|
||||
@ -265,7 +265,7 @@ FEATURE_SET Classify::ExtractIntGeoFeatures(
|
||||
GenericVector<INT_FEATURE_STRUCT> bl_features;
|
||||
tesseract::TrainingSample* sample = tesseract::BlobToTrainingSample(
|
||||
blob, false, &local_fx_info, &bl_features);
|
||||
if (sample == NULL) return NULL;
|
||||
if (sample == nullptr) return nullptr;
|
||||
|
||||
FEATURE_SET feature_set = NewFeatureSet(1);
|
||||
FEATURE feature = NewFeature(&IntFeatDesc);
|
||||
|
@ -53,8 +53,8 @@ typedef PROTO_STRUCT *PROTO;
|
||||
|
||||
struct CLASS_STRUCT {
|
||||
CLASS_STRUCT()
|
||||
: NumProtos(0), MaxNumProtos(0), Prototypes(NULL),
|
||||
NumConfigs(0), MaxNumConfigs(0), Configurations(NULL) {
|
||||
: NumProtos(0), MaxNumProtos(0), Prototypes(nullptr),
|
||||
NumConfigs(0), MaxNumConfigs(0), Configurations(nullptr) {
|
||||
}
|
||||
int16_t NumProtos;
|
||||
int16_t MaxNumProtos;
|
||||
|
@ -25,11 +25,11 @@ namespace tesseract {
|
||||
// ================== SampleIterator Implementation =================
|
||||
|
||||
SampleIterator::SampleIterator()
|
||||
: charset_map_(NULL),
|
||||
shape_table_(NULL),
|
||||
sample_set_(NULL),
|
||||
: charset_map_(nullptr),
|
||||
shape_table_(nullptr),
|
||||
sample_set_(nullptr),
|
||||
randomize_(false),
|
||||
owned_shape_table_(NULL) {
|
||||
owned_shape_table_(nullptr) {
|
||||
num_shapes_ = 0;
|
||||
Begin();
|
||||
}
|
||||
@ -40,7 +40,7 @@ SampleIterator::~SampleIterator() {
|
||||
|
||||
void SampleIterator::Clear() {
|
||||
delete owned_shape_table_;
|
||||
owned_shape_table_ = NULL;
|
||||
owned_shape_table_ = nullptr;
|
||||
}
|
||||
|
||||
// See class comment for arguments.
|
||||
@ -53,7 +53,7 @@ void SampleIterator::Init(const IndexMapBiDi* charset_map,
|
||||
shape_table_ = shape_table;
|
||||
sample_set_ = sample_set;
|
||||
randomize_ = randomize;
|
||||
if (shape_table_ == NULL && charset_map_ != NULL) {
|
||||
if (shape_table_ == nullptr && charset_map_ != nullptr) {
|
||||
// The caller wishes to iterate by class. The easiest way to do this
|
||||
// is to create a dummy shape_table_ that we will own.
|
||||
int num_fonts = sample_set_->NumFonts();
|
||||
@ -71,7 +71,7 @@ void SampleIterator::Init(const IndexMapBiDi* charset_map,
|
||||
}
|
||||
shape_table_ = owned_shape_table_;
|
||||
}
|
||||
if (shape_table_ != NULL) {
|
||||
if (shape_table_ != nullptr) {
|
||||
num_shapes_ = shape_table_->NumShapes();
|
||||
} else {
|
||||
num_shapes_ = randomize ? sample_set_->num_samples()
|
||||
@ -101,7 +101,7 @@ bool SampleIterator::AtEnd() const {
|
||||
}
|
||||
|
||||
const TrainingSample& SampleIterator::GetSample() const {
|
||||
if (shape_table_ != NULL) {
|
||||
if (shape_table_ != nullptr) {
|
||||
const UnicharAndFonts* shape_entry = GetShapeEntry();
|
||||
int char_id = shape_entry->unichar_id;
|
||||
int font_id = shape_entry->font_ids[shape_font_index_];
|
||||
@ -112,7 +112,7 @@ const TrainingSample& SampleIterator::GetSample() const {
|
||||
}
|
||||
|
||||
TrainingSample* SampleIterator::MutableSample() const {
|
||||
if (shape_table_ != NULL) {
|
||||
if (shape_table_ != nullptr) {
|
||||
const UnicharAndFonts* shape_entry = GetShapeEntry();
|
||||
int char_id = shape_entry->unichar_id;
|
||||
int font_id = shape_entry->font_ids[shape_font_index_];
|
||||
@ -125,7 +125,7 @@ TrainingSample* SampleIterator::MutableSample() const {
|
||||
// Returns the total index (from the original set of samples) of the current
|
||||
// sample.
|
||||
int SampleIterator::GlobalSampleIndex() const {
|
||||
if (shape_table_ != NULL) {
|
||||
if (shape_table_ != nullptr) {
|
||||
const UnicharAndFonts* shape_entry = GetShapeEntry();
|
||||
int char_id = shape_entry->unichar_id;
|
||||
int font_id = shape_entry->font_ids[shape_font_index_];
|
||||
@ -138,9 +138,9 @@ int SampleIterator::GlobalSampleIndex() const {
|
||||
// Returns the index of the current sample in compact charset space, so
|
||||
// in a 2-class problem between x and y, the returned indices will all be
|
||||
// 0 or 1, and have nothing to do with the unichar_ids.
|
||||
// If the charset_map_ is NULL, then this is equal to GetSparseClassID().
|
||||
// If the charset_map_ is nullptr, then this is equal to GetSparseClassID().
|
||||
int SampleIterator::GetCompactClassID() const {
|
||||
return charset_map_ != NULL ? charset_map_->SparseToCompact(shape_index_)
|
||||
return charset_map_ != nullptr ? charset_map_->SparseToCompact(shape_index_)
|
||||
: GetSparseClassID();
|
||||
}
|
||||
// Returns the index of the current sample in sparse charset space, so
|
||||
@ -148,13 +148,13 @@ int SampleIterator::GetCompactClassID() const {
|
||||
// x or y, where x and y may be unichar_ids (no shape_table_) or shape_ids
|
||||
// with a shape_table_.
|
||||
int SampleIterator::GetSparseClassID() const {
|
||||
return shape_table_ != NULL ? shape_index_ : GetSample().class_id();
|
||||
return shape_table_ != nullptr ? shape_index_ : GetSample().class_id();
|
||||
}
|
||||
|
||||
// Moves on to the next indexable sample. If the end is reached, leaves
|
||||
// the state such that AtEnd() is true.
|
||||
void SampleIterator::Next() {
|
||||
if (shape_table_ != NULL) {
|
||||
if (shape_table_ != nullptr) {
|
||||
// Next sample in this class/font combination.
|
||||
++sample_index_;
|
||||
if (sample_index_ < num_samples_)
|
||||
@ -173,7 +173,7 @@ void SampleIterator::Next() {
|
||||
do {
|
||||
++shape_index_;
|
||||
} while (shape_index_ < num_shapes_ &&
|
||||
charset_map_ != NULL &&
|
||||
charset_map_ != nullptr &&
|
||||
charset_map_->SparseToCompact(shape_index_) < 0);
|
||||
if (shape_index_ >= num_shapes_)
|
||||
return; // The end.
|
||||
@ -194,15 +194,15 @@ void SampleIterator::Next() {
|
||||
|
||||
// Returns the size of the compact charset space.
|
||||
int SampleIterator::CompactCharsetSize() const {
|
||||
return charset_map_ != NULL ? charset_map_->CompactSize()
|
||||
return charset_map_ != nullptr ? charset_map_->CompactSize()
|
||||
: SparseCharsetSize();
|
||||
}
|
||||
|
||||
// Returns the size of the sparse charset space.
|
||||
int SampleIterator::SparseCharsetSize() const {
|
||||
return charset_map_ != NULL
|
||||
return charset_map_ != nullptr
|
||||
? charset_map_->SparseSize()
|
||||
: (shape_table_ != NULL ? shape_table_->NumShapes()
|
||||
: (shape_table_ != nullptr ? shape_table_->NumShapes()
|
||||
: sample_set_->charsetsize());
|
||||
}
|
||||
|
||||
|
@ -30,10 +30,10 @@ struct UnicharAndFonts;
|
||||
// all samples of all shapes needed for a classification problem.
|
||||
//
|
||||
// =====INPUTS TO Init FUNCTION=====
|
||||
// The charset_map defines a subset of the sample_set classes (with a NULL
|
||||
// shape_table, or the shape_table classes if not NULL.)
|
||||
// The charset_map defines a subset of the sample_set classes (with a nullptr
|
||||
// shape_table, or the shape_table classes if not nullptr.)
|
||||
//
|
||||
// The shape_table (if not NULL) defines the mapping from shapes to
|
||||
// The shape_table (if not nullptr) defines the mapping from shapes to
|
||||
// font_id/class_id pairs. Each shape is a list of unichar_id and font lists.
|
||||
//
|
||||
// The sample_set holds the samples and provides indexed access to samples
|
||||
@ -44,16 +44,16 @@ struct UnicharAndFonts;
|
||||
// iterations.
|
||||
//
|
||||
// =====DIFFERENT COMBINATIONS OF INPUTS=====
|
||||
// NULL shape_table:
|
||||
// nullptr shape_table:
|
||||
// Without a shape_table, everything works in UNICHAR_IDs.
|
||||
//
|
||||
// NULL shape_table, NULL charset_map:
|
||||
// nullptr shape_table, nullptr charset_map:
|
||||
// Iterations simply run over the samples in the order the samples occur in the
|
||||
// input files.
|
||||
// GetCompactClassID and GetSparseClassID both return the sample UNICHAR_ID.
|
||||
//
|
||||
// NULL shape_table, non-NULL charset_map:
|
||||
// When shape_table is NULL, the charset_map indexes unichar_ids directly,
|
||||
// nullptr shape_table, non-nullptr charset_map:
|
||||
// When shape_table is nullptr, the charset_map indexes unichar_ids directly,
|
||||
// and an iteration returns all samples of all chars in the charset_map, which
|
||||
// is a subset of the full unicharset.
|
||||
// The iteration will be in groups of the same unichar_id, in the order
|
||||
@ -61,18 +61,18 @@ struct UnicharAndFonts;
|
||||
// GetCompactClassID returns the charset_map index of a sample, and
|
||||
// GetSparseClassID returns the sample UNICHAR_ID.
|
||||
//
|
||||
// Non-NULL shape_table:
|
||||
// Non-nullptr shape_table:
|
||||
// With a shape_table, samples are grouped according to the shape_table, so
|
||||
// multiple UNICHAR_IDs and fonts may be grouped together, and everything
|
||||
// works in shape_ids.
|
||||
//
|
||||
// Non-NULL shape_table, NULL charset_map.
|
||||
// Non-nullptr shape_table, nullptr charset_map.
|
||||
// Iterations simply run over the samples in the order of shape_id.
|
||||
// GetCompactClassID and GetSparseClassID both return the shape_id.
|
||||
// (If you want the unichar_id or font_id, the sample still has them.)
|
||||
//
|
||||
// Non-NULL shape_table, non-NULL charset_map.
|
||||
// When shape_table is not NULL, the charset_map indexes and subsets shapes in
|
||||
// Non-nullptr shape_table, non-nullptr charset_map.
|
||||
// When shape_table is not nullptr, the charset_map indexes and subsets shapes in
|
||||
// the shape_table, and iterations will be in shape_table order, not
|
||||
// charset_map order.
|
||||
// GetCompactClassID returns the charset_map index of a shape, and
|
||||
@ -118,7 +118,7 @@ class SampleIterator {
|
||||
// Returns the index of the current sample in compact charset space, so
|
||||
// in a 2-class problem between x and y, the returned indices will all be
|
||||
// 0 or 1, and have nothing to do with the unichar_ids.
|
||||
// If the charset_map_ is NULL, then this is equal to GetSparseClassID().
|
||||
// If the charset_map_ is nullptr, then this is equal to GetSparseClassID().
|
||||
int GetCompactClassID() const;
|
||||
// Returns the index of the current sample in sparse charset space, so
|
||||
// in a 2-class problem between x and y, the returned indices will all be
|
||||
|
@ -59,12 +59,12 @@ int ShapeClassifier::UnicharClassifySample(
|
||||
int ShapeClassifier::ClassifySample(const TrainingSample& sample, Pix* page_pix,
|
||||
int debug, int keep_this,
|
||||
GenericVector<ShapeRating>* results) {
|
||||
ASSERT_HOST("Must implement ClassifySample!" == NULL);
|
||||
ASSERT_HOST("Must implement ClassifySample!" == nullptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns the shape that contains unichar_id that has the best result.
|
||||
// If result is not NULL, it is set with the shape_id and rating.
|
||||
// If result is not nullptr, it is set with the shape_id and rating.
|
||||
// Does not need to be overridden if ClassifySample respects the keep_this
|
||||
// rule.
|
||||
int ShapeClassifier::BestShapeForUnichar(const TrainingSample& sample,
|
||||
@ -75,7 +75,7 @@ int ShapeClassifier::BestShapeForUnichar(const TrainingSample& sample,
|
||||
int num_results = ClassifySample(sample, page_pix, 0, unichar_id, &results);
|
||||
for (int r = 0; r < num_results; ++r) {
|
||||
if (shapes->GetShape(results[r].shape_id).ContainsUnichar(unichar_id)) {
|
||||
if (result != NULL)
|
||||
if (result != nullptr)
|
||||
*result = results[r];
|
||||
return results[r].shape_id;
|
||||
}
|
||||
@ -84,7 +84,7 @@ int ShapeClassifier::BestShapeForUnichar(const TrainingSample& sample,
|
||||
}
|
||||
|
||||
// Provides access to the UNICHARSET that this classifier works with.
|
||||
// Only needs to be overridden if GetShapeTable() can return NULL.
|
||||
// Only needs to be overridden if GetShapeTable() can return nullptr.
|
||||
const UNICHARSET& ShapeClassifier::GetUnicharset() const {
|
||||
return GetShapeTable()->unicharset();
|
||||
}
|
||||
@ -98,8 +98,8 @@ void ShapeClassifier::DebugDisplay(const TrainingSample& sample,
|
||||
Pix* page_pix,
|
||||
UNICHAR_ID unichar_id) {
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
static ScrollView* terminator = NULL;
|
||||
if (terminator == NULL) {
|
||||
static ScrollView* terminator = nullptr;
|
||||
if (terminator == nullptr) {
|
||||
terminator = new ScrollView("XIT", 0, 0, 50, 50, 50, 50, true);
|
||||
}
|
||||
ScrollView* debug_win = CreateFeatureSpaceWindow("ClassifierDebug", 0, 0);
|
||||
|
@ -45,7 +45,7 @@ class ShapeClassifier {
|
||||
virtual ~ShapeClassifier() {}
|
||||
|
||||
// Classifies the given [training] sample, writing to results.
|
||||
// If page_pix is not NULL, the overriding function may call
|
||||
// If page_pix is not nullptr, the overriding function may call
|
||||
// sample.GetSamplePix(padding, page_pix) to get an image of the sample
|
||||
// padded (with real image data) by the given padding to extract features
|
||||
// from the image of the character. Other members of TrainingSample:
|
||||
@ -75,7 +75,7 @@ class ShapeClassifier {
|
||||
|
||||
public:
|
||||
// Returns the shape that contains unichar_id that has the best result.
|
||||
// If result is not NULL, it is set with the shape_id and rating.
|
||||
// If result is not nullptr, it is set with the shape_id and rating.
|
||||
// Returns -1 if ClassifySample fails to provide any result containing
|
||||
// unichar_id. BestShapeForUnichar does not need to be overridden if
|
||||
// ClassifySample respects the keep_this rule.
|
||||
@ -85,7 +85,7 @@ class ShapeClassifier {
|
||||
// Provides access to the ShapeTable that this classifier works with.
|
||||
virtual const ShapeTable* GetShapeTable() const = 0;
|
||||
// Provides access to the UNICHARSET that this classifier works with.
|
||||
// Must be overridden IFF GetShapeTable() returns NULL.
|
||||
// Must be overridden IFF GetShapeTable() returns nullptr.
|
||||
virtual const UNICHARSET& GetUnicharset() const;
|
||||
|
||||
// Visual debugger classifies the given sample, displays the results and
|
||||
|
@ -236,7 +236,7 @@ void Shape::SortUnichars() {
|
||||
unichars_sorted_ = true;
|
||||
}
|
||||
|
||||
ShapeTable::ShapeTable() : unicharset_(NULL), num_fonts_(0) {
|
||||
ShapeTable::ShapeTable() : unicharset_(nullptr), num_fonts_(0) {
|
||||
}
|
||||
ShapeTable::ShapeTable(const UNICHARSET& unicharset)
|
||||
: unicharset_(&unicharset), num_fonts_(0) {
|
||||
@ -366,7 +366,7 @@ int ShapeTable::AddShape(const Shape& other) {
|
||||
// Removes the shape given by the shape index.
|
||||
void ShapeTable::DeleteShape(int shape_id) {
|
||||
delete shape_table_[shape_id];
|
||||
shape_table_[shape_id] = NULL;
|
||||
shape_table_[shape_id] = nullptr;
|
||||
shape_table_.remove(shape_id);
|
||||
}
|
||||
|
||||
@ -484,7 +484,7 @@ void ShapeTable::ForceFontMerges(int start, int end) {
|
||||
}
|
||||
}
|
||||
ShapeTable compacted(*unicharset_);
|
||||
compacted.AppendMasterShapes(*this, NULL);
|
||||
compacted.AppendMasterShapes(*this, nullptr);
|
||||
*this = compacted;
|
||||
}
|
||||
|
||||
@ -658,15 +658,15 @@ bool ShapeTable::CommonFont(int shape_id1, int shape_id2) const {
|
||||
}
|
||||
|
||||
// Appends the master shapes from other to this.
|
||||
// If not NULL, shape_map is set to map other shape_ids to this's shape_ids.
|
||||
// If not nullptr, shape_map is set to map other shape_ids to this's shape_ids.
|
||||
void ShapeTable::AppendMasterShapes(const ShapeTable& other,
|
||||
GenericVector<int>* shape_map) {
|
||||
if (shape_map != NULL)
|
||||
if (shape_map != nullptr)
|
||||
shape_map->init_to_size(other.NumShapes(), -1);
|
||||
for (int s = 0; s < other.shape_table_.size(); ++s) {
|
||||
if (other.shape_table_[s]->destination_index() < 0) {
|
||||
int index = AddShape(*other.shape_table_[s]);
|
||||
if (shape_map != NULL)
|
||||
if (shape_map != nullptr)
|
||||
(*shape_map)[s] = index;
|
||||
}
|
||||
}
|
||||
|
@ -350,7 +350,7 @@ class ShapeTable {
|
||||
// Appends the master shapes from other to this.
|
||||
// Used to create a clean ShapeTable from a merged one, or to create a
|
||||
// copy of a ShapeTable.
|
||||
// If not NULL, shape_map is set to map other shape_ids to this's shape_ids.
|
||||
// If not nullptr, shape_map is set to map other shape_ids to this's shape_ids.
|
||||
void AppendMasterShapes(const ShapeTable& other,
|
||||
GenericVector<int>* shape_map);
|
||||
// Returns the number of master shapes remaining after merging.
|
||||
|
@ -55,7 +55,7 @@ const ShapeTable* TessClassifier::GetShapeTable() const {
|
||||
return classify_->shape_table();
|
||||
}
|
||||
// Provides access to the UNICHARSET that this classifier works with.
|
||||
// Only needs to be overridden if GetShapeTable() can return NULL.
|
||||
// Only needs to be overridden if GetShapeTable() can return nullptr.
|
||||
const UNICHARSET& TessClassifier::GetUnicharset() const {
|
||||
return classify_->unicharset;
|
||||
}
|
||||
@ -70,8 +70,8 @@ int TessClassifier::DisplayClassifyAs(
|
||||
PointerVector<ScrollView>* windows) {
|
||||
int shape_id = unichar_id;
|
||||
// TODO(rays) Fix this so it works with both flat and real shapetables.
|
||||
// if (GetShapeTable() != NULL)
|
||||
// shape_id = BestShapeForUnichar(sample, page_pix, unichar_id, NULL);
|
||||
// if (GetShapeTable() != nullptr)
|
||||
// shape_id = BestShapeForUnichar(sample, page_pix, unichar_id, nullptr);
|
||||
if (shape_id < 0) return index;
|
||||
if (UnusedClassIdIn(classify_->PreTrainedTemplates, shape_id)) {
|
||||
tprintf("No built-in templates for class/shape %d\n", shape_id);
|
||||
|
@ -32,7 +32,7 @@ class TrainingSample;
|
||||
// Tesseract implementation of a ShapeClassifier.
|
||||
// Due to limitations in the content of TrainingSample, this currently
|
||||
// only works for the static classifier and only works if the ShapeTable
|
||||
// in classify is not NULL.
|
||||
// in classify is not nullptr.
|
||||
class TessClassifier : public ShapeClassifier {
|
||||
public:
|
||||
TessClassifier(bool pruner_only, tesseract::Classify* classify)
|
||||
@ -47,7 +47,7 @@ class TessClassifier : public ShapeClassifier {
|
||||
// Provides access to the ShapeTable that this classifier works with.
|
||||
virtual const ShapeTable* GetShapeTable() const;
|
||||
// Provides access to the UNICHARSET that this classifier works with.
|
||||
// Only needs to be overridden if GetShapeTable() can return NULL.
|
||||
// Only needs to be overridden if GetShapeTable() can return nullptr.
|
||||
virtual const UNICHARSET& GetUnicharset() const;
|
||||
|
||||
// Displays classification as the given shape_id. Creates as many windows
|
||||
|
@ -75,13 +75,13 @@ bool TrainingSample::Serialize(FILE* fp) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Creates from the given file. Returns NULL in case of error.
|
||||
// Creates from the given file. Returns nullptr in case of error.
|
||||
// If swap is true, assumes a big/little-endian swap is needed.
|
||||
TrainingSample* TrainingSample::DeSerializeCreate(bool swap, FILE* fp) {
|
||||
TrainingSample* sample = new TrainingSample;
|
||||
if (sample->DeSerialize(swap, fp)) return sample;
|
||||
delete sample;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Reads from the given file. Returns false in case of error.
|
||||
@ -209,11 +209,11 @@ void TrainingSample::ExtractCharDesc(int int_feature_type,
|
||||
// Extract the INT features.
|
||||
delete[] features_;
|
||||
FEATURE_SET_STRUCT* char_features = char_desc->FeatureSets[int_feature_type];
|
||||
if (char_features == NULL) {
|
||||
if (char_features == nullptr) {
|
||||
tprintf("Error: no features to train on of type %s\n",
|
||||
kIntFeatureType);
|
||||
num_features_ = 0;
|
||||
features_ = NULL;
|
||||
features_ = nullptr;
|
||||
} else {
|
||||
num_features_ = char_features->NumFeatures;
|
||||
features_ = new INT_FEATURE_STRUCT[num_features_];
|
||||
@ -230,11 +230,11 @@ void TrainingSample::ExtractCharDesc(int int_feature_type,
|
||||
// Extract the Micro features.
|
||||
delete[] micro_features_;
|
||||
char_features = char_desc->FeatureSets[micro_type];
|
||||
if (char_features == NULL) {
|
||||
if (char_features == nullptr) {
|
||||
tprintf("Error: no features to train on of type %s\n",
|
||||
kMicroFeatureType);
|
||||
num_micro_features_ = 0;
|
||||
micro_features_ = NULL;
|
||||
micro_features_ = nullptr;
|
||||
} else {
|
||||
num_micro_features_ = char_features->NumFeatures;
|
||||
micro_features_ = new MicroFeature[num_micro_features_];
|
||||
@ -246,7 +246,7 @@ void TrainingSample::ExtractCharDesc(int int_feature_type,
|
||||
}
|
||||
// Extract the CN feature.
|
||||
char_features = char_desc->FeatureSets[cn_type];
|
||||
if (char_features == NULL) {
|
||||
if (char_features == nullptr) {
|
||||
tprintf("Error: no CN feature to train on.\n");
|
||||
} else {
|
||||
ASSERT_HOST(char_features->NumFeatures == 1);
|
||||
@ -258,7 +258,7 @@ void TrainingSample::ExtractCharDesc(int int_feature_type,
|
||||
}
|
||||
// Extract the Geo feature.
|
||||
char_features = char_desc->FeatureSets[geo_type];
|
||||
if (char_features == NULL) {
|
||||
if (char_features == nullptr) {
|
||||
tprintf("Error: no Geo feature to train on.\n");
|
||||
} else {
|
||||
ASSERT_HOST(char_features->NumFeatures == 1);
|
||||
@ -306,7 +306,7 @@ Pix* TrainingSample::RenderToPix(const UNICHARSET* unicharset) const {
|
||||
pixSetPixel(pix, x, y, 1);
|
||||
}
|
||||
}
|
||||
if (unicharset != NULL)
|
||||
if (unicharset != nullptr)
|
||||
pixSetText(pix, unicharset->id_to_unichar(class_id_));
|
||||
return pix;
|
||||
}
|
||||
@ -324,10 +324,10 @@ void TrainingSample::DisplayFeatures(ScrollView::Color color,
|
||||
// Returns a pix of the original sample image. The pix is padded all round
|
||||
// by padding wherever possible.
|
||||
// The returned Pix must be pixDestroyed after use.
|
||||
// If the input page_pix is NULL, NULL is returned.
|
||||
// If the input page_pix is nullptr, nullptr is returned.
|
||||
Pix* TrainingSample::GetSamplePix(int padding, Pix* page_pix) const {
|
||||
if (page_pix == NULL)
|
||||
return NULL;
|
||||
if (page_pix == nullptr)
|
||||
return nullptr;
|
||||
int page_width = pixGetWidth(page_pix);
|
||||
int page_height = pixGetHeight(page_pix);
|
||||
TBOX padded_box = bounding_box();
|
||||
@ -337,7 +337,7 @@ Pix* TrainingSample::GetSamplePix(int padding, Pix* page_pix) const {
|
||||
padded_box &= page_box;
|
||||
Box* box = boxCreate(page_box.left(), page_height - page_box.top(),
|
||||
page_box.width(), page_box.height());
|
||||
Pix* sample_pix = pixClipRectangle(page_pix, box, NULL);
|
||||
Pix* sample_pix = pixClipRectangle(page_pix, box, nullptr);
|
||||
boxDestroy(&box);
|
||||
return sample_pix;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ class TrainingSample : public ELIST_LINK {
|
||||
TrainingSample()
|
||||
: class_id_(INVALID_UNICHAR_ID), font_id_(0), page_num_(0),
|
||||
num_features_(0), num_micro_features_(0), outline_length_(0),
|
||||
features_(NULL), micro_features_(NULL), weight_(1.0),
|
||||
features_(nullptr), micro_features_(nullptr), weight_(1.0),
|
||||
max_dist_(0.0), sample_index_(0),
|
||||
features_are_indexed_(false), features_are_mapped_(false),
|
||||
is_error_(false) {
|
||||
@ -82,7 +82,7 @@ class TrainingSample : public ELIST_LINK {
|
||||
// It is assumed these can all be reconstructed from what is saved.
|
||||
// Writes to the given file. Returns false in case of error.
|
||||
bool Serialize(FILE* fp) const;
|
||||
// Creates from the given file. Returns NULL in case of error.
|
||||
// Creates from the given file. Returns nullptr in case of error.
|
||||
// If swap is true, assumes a big/little-endian swap is needed.
|
||||
static TrainingSample* DeSerializeCreate(bool swap, FILE* fp);
|
||||
// Reads from the given file. Returns false in case of error.
|
||||
@ -109,7 +109,7 @@ class TrainingSample : public ELIST_LINK {
|
||||
// Returns a pix of the original sample image. The pix is padded all round
|
||||
// by padding wherever possible.
|
||||
// The returned Pix must be pixDestroyed after use.
|
||||
// If the input page_pix is NULL, NULL is returned.
|
||||
// If the input page_pix is nullptr, nullptr is returned.
|
||||
Pix* GetSamplePix(int padding, Pix* page_pix) const;
|
||||
|
||||
// Accessors.
|
||||
|
@ -69,7 +69,7 @@ bool TrainingSampleSet::FontClassInfo::DeSerialize(bool swap, FILE* fp) {
|
||||
|
||||
TrainingSampleSet::TrainingSampleSet(const FontInfoTable& font_table)
|
||||
: num_raw_samples_(0), unicharset_size_(0),
|
||||
font_class_array_(NULL), fontinfo_table_(font_table) {
|
||||
font_class_array_(nullptr), fontinfo_table_(font_table) {
|
||||
}
|
||||
|
||||
TrainingSampleSet::~TrainingSampleSet() {
|
||||
@ -81,7 +81,7 @@ bool TrainingSampleSet::Serialize(FILE* fp) const {
|
||||
if (!samples_.Serialize(fp)) return false;
|
||||
if (!unicharset_.save_to_file(fp)) return false;
|
||||
if (!font_id_map_.Serialize(fp)) return false;
|
||||
int8_t not_null = font_class_array_ != NULL;
|
||||
int8_t not_null = font_class_array_ != nullptr;
|
||||
if (fwrite(¬_null, sizeof(not_null), 1, fp) != 1) return false;
|
||||
if (not_null) {
|
||||
if (!font_class_array_->SerializeClasses(fp)) return false;
|
||||
@ -97,7 +97,7 @@ bool TrainingSampleSet::DeSerialize(bool swap, FILE* fp) {
|
||||
if (!unicharset_.load_from_file(fp)) return false;
|
||||
if (!font_id_map_.DeSerialize(swap, fp)) return false;
|
||||
delete font_class_array_;
|
||||
font_class_array_ = NULL;
|
||||
font_class_array_ = nullptr;
|
||||
int8_t not_null;
|
||||
if (fread(¬_null, sizeof(not_null), 1, fp) != 1) return false;
|
||||
if (not_null) {
|
||||
@ -155,7 +155,7 @@ void TrainingSampleSet::AddSample(int unichar_id, TrainingSample* sample) {
|
||||
// OrganizeByFontAndClass must have been already called.
|
||||
int TrainingSampleSet::NumClassSamples(int font_id, int class_id,
|
||||
bool randomize) const {
|
||||
ASSERT_HOST(font_class_array_ != NULL);
|
||||
ASSERT_HOST(font_class_array_ != nullptr);
|
||||
if (font_id < 0 || class_id < 0 ||
|
||||
font_id >= font_id_map_.SparseSize() || class_id >= unicharset_size_) {
|
||||
// There are no samples because the font or class doesn't exist.
|
||||
@ -179,9 +179,9 @@ const TrainingSample* TrainingSampleSet::GetSample(int index) const {
|
||||
// OrganizeByFontAndClass must have been already called.
|
||||
const TrainingSample* TrainingSampleSet::GetSample(int font_id, int class_id,
|
||||
int index) const {
|
||||
ASSERT_HOST(font_class_array_ != NULL);
|
||||
ASSERT_HOST(font_class_array_ != nullptr);
|
||||
int font_index = font_id_map_.SparseToCompact(font_id);
|
||||
if (font_index < 0) return NULL;
|
||||
if (font_index < 0) return nullptr;
|
||||
int sample_index = (*font_class_array_)(font_index, class_id).samples[index];
|
||||
return samples_[sample_index];
|
||||
}
|
||||
@ -190,9 +190,9 @@ const TrainingSample* TrainingSampleSet::GetSample(int font_id, int class_id,
|
||||
// OrganizeByFontAndClass must have been already called.
|
||||
TrainingSample* TrainingSampleSet::MutableSample(int font_id, int class_id,
|
||||
int index) {
|
||||
ASSERT_HOST(font_class_array_ != NULL);
|
||||
ASSERT_HOST(font_class_array_ != nullptr);
|
||||
int font_index = font_id_map_.SparseToCompact(font_id);
|
||||
if (font_index < 0) return NULL;
|
||||
if (font_index < 0) return nullptr;
|
||||
int sample_index = (*font_class_array_)(font_index, class_id).samples[index];
|
||||
return samples_[sample_index];
|
||||
}
|
||||
@ -296,7 +296,7 @@ float TrainingSampleSet::UnicharDistance(const UnicharAndFonts& uf1,
|
||||
float TrainingSampleSet::ClusterDistance(int font_id1, int class_id1,
|
||||
int font_id2, int class_id2,
|
||||
const IntFeatureMap& feature_map) {
|
||||
ASSERT_HOST(font_class_array_ != NULL);
|
||||
ASSERT_HOST(font_class_array_ != nullptr);
|
||||
int font_index1 = font_id_map_.SparseToCompact(font_id1);
|
||||
int font_index2 = font_id_map_.SparseToCompact(font_id2);
|
||||
if (font_index1 < 0 || font_index2 < 0)
|
||||
@ -416,7 +416,7 @@ int TrainingSampleSet::ReliablySeparable(int font_id1, int class_id1,
|
||||
bool thorough) const {
|
||||
int result = 0;
|
||||
const TrainingSample* sample2 = GetCanonicalSample(font_id2, class_id2);
|
||||
if (sample2 == NULL)
|
||||
if (sample2 == nullptr)
|
||||
return 0; // There are no canonical features.
|
||||
const GenericVector<int>& canonical2 = GetCanonicalFeatures(font_id2,
|
||||
class_id2);
|
||||
@ -451,7 +451,7 @@ int TrainingSampleSet::ReliablySeparable(int font_id1, int class_id1,
|
||||
// OrganizeByFontAndClass must have been already called.
|
||||
int TrainingSampleSet::GlobalSampleIndex(int font_id, int class_id,
|
||||
int index) const {
|
||||
ASSERT_HOST(font_class_array_ != NULL);
|
||||
ASSERT_HOST(font_class_array_ != nullptr);
|
||||
int font_index = font_id_map_.SparseToCompact(font_id);
|
||||
if (font_index < 0) return -1;
|
||||
return (*font_class_array_)(font_index, class_id).samples[index];
|
||||
@ -461,18 +461,18 @@ int TrainingSampleSet::GlobalSampleIndex(int font_id, int class_id,
|
||||
// ComputeCanonicalSamples must have been called first.
|
||||
const TrainingSample* TrainingSampleSet::GetCanonicalSample(
|
||||
int font_id, int class_id) const {
|
||||
ASSERT_HOST(font_class_array_ != NULL);
|
||||
ASSERT_HOST(font_class_array_ != nullptr);
|
||||
int font_index = font_id_map_.SparseToCompact(font_id);
|
||||
if (font_index < 0) return NULL;
|
||||
if (font_index < 0) return nullptr;
|
||||
int sample_index = (*font_class_array_)(font_index,
|
||||
class_id).canonical_sample;
|
||||
return sample_index >= 0 ? samples_[sample_index] : NULL;
|
||||
return sample_index >= 0 ? samples_[sample_index] : nullptr;
|
||||
}
|
||||
|
||||
// Gets the max distance for the given canonical sample.
|
||||
// ComputeCanonicalSamples must have been called first.
|
||||
float TrainingSampleSet::GetCanonicalDist(int font_id, int class_id) const {
|
||||
ASSERT_HOST(font_class_array_ != NULL);
|
||||
ASSERT_HOST(font_class_array_ != nullptr);
|
||||
int font_index = font_id_map_.SparseToCompact(font_id);
|
||||
if (font_index < 0) return 0.0f;
|
||||
if ((*font_class_array_)(font_index, class_id).canonical_sample >= 0)
|
||||
@ -504,7 +504,7 @@ void TrainingSampleSet::DeleteDeadSamples() {
|
||||
// Callback function returns true if the given sample is to be deleted, due
|
||||
// to having a negative classid.
|
||||
bool TrainingSampleSet::DeleteableSample(const TrainingSample* sample) {
|
||||
return sample == NULL || sample->class_id() < 0;
|
||||
return sample == nullptr || sample->class_id() < 0;
|
||||
}
|
||||
|
||||
// Construct an array to access the samples by font,class pair.
|
||||
@ -514,7 +514,7 @@ void TrainingSampleSet::OrganizeByFontAndClass() {
|
||||
SetupFontIdMap();
|
||||
int compact_font_size = font_id_map_.CompactSize();
|
||||
// Get a 2-d array of generic vectors.
|
||||
if (font_class_array_ != NULL)
|
||||
if (font_class_array_ != nullptr)
|
||||
delete font_class_array_;
|
||||
FontClassInfo empty;
|
||||
font_class_array_ = new GENERIC_2D_ARRAY<FontClassInfo>(
|
||||
@ -568,7 +568,7 @@ void TrainingSampleSet::SetupFontIdMap() {
|
||||
// OrganizeByFontAndClass must have been already called.
|
||||
void TrainingSampleSet::ComputeCanonicalSamples(const IntFeatureMap& map,
|
||||
bool debug) {
|
||||
ASSERT_HOST(font_class_array_ != NULL);
|
||||
ASSERT_HOST(font_class_array_ != nullptr);
|
||||
IntFeatureDist f_table;
|
||||
if (debug) tprintf("feature table size %d\n", map.sparse_size());
|
||||
f_table.Init(&map);
|
||||
@ -663,7 +663,7 @@ void TrainingSampleSet::ComputeCanonicalSamples(const IntFeatureMap& map,
|
||||
// in a predictable and repeatable way.
|
||||
// Use after OrganizeByFontAndClass().
|
||||
void TrainingSampleSet::ReplicateAndRandomizeSamples() {
|
||||
ASSERT_HOST(font_class_array_ != NULL);
|
||||
ASSERT_HOST(font_class_array_ != nullptr);
|
||||
int font_size = font_id_map_.CompactSize();
|
||||
for (int font_index = 0; font_index < font_size; ++font_index) {
|
||||
for (int c = 0; c < unicharset_size_; ++c) {
|
||||
@ -692,7 +692,7 @@ void TrainingSampleSet::ReplicateAndRandomizeSamples() {
|
||||
// TODO(rays) see note on ReliablySeparable and try restricting the
|
||||
// canonical features to those that truly represent all samples.
|
||||
void TrainingSampleSet::ComputeCanonicalFeatures() {
|
||||
ASSERT_HOST(font_class_array_ != NULL);
|
||||
ASSERT_HOST(font_class_array_ != nullptr);
|
||||
int font_size = font_id_map_.CompactSize();
|
||||
for (int font_index = 0; font_index < font_size; ++font_index) {
|
||||
int font_id = font_id_map_.CompactToSparse(font_index);
|
||||
@ -710,7 +710,7 @@ void TrainingSampleSet::ComputeCanonicalFeatures() {
|
||||
// Computes the combined set of features used by all the samples of each
|
||||
// font/class combination. Use after ReplicateAndRandomizeSamples.
|
||||
void TrainingSampleSet::ComputeCloudFeatures(int feature_space_size) {
|
||||
ASSERT_HOST(font_class_array_ != NULL);
|
||||
ASSERT_HOST(font_class_array_ != nullptr);
|
||||
int font_size = font_id_map_.CompactSize();
|
||||
for (int font_index = 0; font_index < font_size; ++font_index) {
|
||||
int font_id = font_id_map_.CompactToSparse(font_index);
|
||||
|
@ -164,7 +164,7 @@ class TrainingSampleSet {
|
||||
// Gets ownership of the sample with the given index, removing it from this.
|
||||
TrainingSample* extract_sample(int index) {
|
||||
TrainingSample* sample = samples_[index];
|
||||
samples_[index] = NULL;
|
||||
samples_[index] = nullptr;
|
||||
return sample;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user