I'm trying to use tesseract to recognize numbers. It works pretty well but sometimes I get wrong results (8 instead of 9 etc). I know how to improve accuracy with some non-ocr methods but I need other results with confidence levels. I found out that I get the best choices using a ChoiceIterator for each ResultIterator:
tesseract::TessBaseAPI tess;
tess.SetPageSegMode(tesseract::PSM_SINGLE_CHAR);
tess.SetVariable("save_best_choices", "T");
[setting input image here]
tess.Recognize(NULL);
tesseract::ResultIterator* ri = tess.GetIterator();
tesseract::ChoiceIterator* ci;
if(ri != 0)
{
char* symbol = ri->GetUTF8Text(tesseract::RIL_SYMBOL);
if(symbol != 0)
{
float conf = ri->Confidence(tesseract::RIL_SYMBOL);
cout << symbol << "\tconf: " << conf << "\n";
const tesseract::ResultIterator itr = *ri;
ci = new tesseract::ChoiceIterator(itr);
do {
const char* choice = ci->GetUTF8Text();
if (choice) {
std::cout << "\t" << choice << " conf: " << ci->Confidence() << "\n";
}
} while(ci->Next());
// delete[] symbol;
}
}
But the problem is that ci->GetUTF8Text() always returns a null pointer.
I'm using tesseract 3.02 as DLL, compiled under MSVC2010 express.
From limited research earlier today, I think the answer might be setting the variable SaveBlobChoices versus SaveBestChoices. I still need to test this myself.
Related
I've not been able to actually get EGM96 to WGS84 transformations to work in PROJ C++. I have however, gotten what I want to work in python, via pyproj, like this:
from pyproj import Transformer, CRS
from pyproj.transformer import TransformerGroup, TransformDirection
from pyproj.datadir import append_data_dir, get_data_dir
def main():
lat = 43.70012234
lng = -79.41629234
z = 100
append_data_dir("/absolute_directory_to/proj/")
transformer = Transformer.from_crs("epsg:4326", "epsg:5773",)
results = transformer.transform(lat, lng, z, None, False, True, TransformDirection.INVERSE)
print(results)
if __name__ == "__main__":
main()
This provides the result:
(43.70012234, -79.41629234, 62.71016021909354)
And the file us_nga_egm96_15.tif located in the ./proj/ directory
However, my replication of the same in C++ doesn't appear to work.
#include <proj.h>
#include <filesystem>
#include <array>
void main(){
auto proj_context = proj_context_create();
const char * path = "/absolute_directory_to/proj";
const char * db_path = proj_context_get_database_path(proj_context);
std::filesystem::path db_path_path = std::filesystem::path(db_path);
std::string db_path_str = db_path_path.parent_path().string();
std::array paths = {path, db_path_str.c_str()};
proj_context_set_search_paths(proj_context, paths.size(), paths.data());
std::cout << proj_errno_string(proj_context_errno(proj_context)) << std::endl;
auto temp = proj_create_crs_to_crs (proj_context,
"EPSG:4326",
"EPSG:5773",
NULL);
std::cout << proj_errno_string(proj_errno(temp)) << std::endl;
std::cout << proj_errno_string(proj_context_errno(proj_context)) << std::endl;
auto b = proj_trans(temp, PJ_INV, {43.70012234,-79.41629234,100,0});
std::cout << proj_errno_string(proj_errno(temp)) << std::endl;
std::cout << proj_errno_string(proj_context_errno(proj_context)) << std::endl;
std::cout << b.v[0] << "," << b.v[1] << "," << b.v[2] << "," << b.v[3] << std::endl;
std::cout << proj_errno_string(proj_errno(temp)) << std::endl;
std::cout << proj_errno_string(proj_context_errno(proj_context)) << std::endl;
proj_destroy(temp);
proj_context_destroy(proj_context);
return 0;
}
It actually prints out nothing (some strange character seems to be eating all the other characters), and in debug mode, I can see that b = {inf,inf,inf,inf}. Same thing happens if I don't manually specify the proj locaiton (but make sure the actual .tiff is located there).
What am I doing wrong here?
Something I didn't mention here, is that I was using VCPKG, due to https://github.com/microsoft/vcpkg/pull/16169, it is actually impossible to use GEO TIFF's on linux for PROJ through VCPKG I would recommend simply not using PROJ through VCPKG at all. The issues that are blocking this from being fixed have been blocked for years at this point, and don't seem to be something that is going to be fixed anytime soon.
seen how data is manually set here: https://raw.githubusercontent.com/Microsoft/vcpkg/master/ports/proj4/portfile.cmake
Stepping through the code, the issue was apparently that I set the correct file location, but that the code silently fails when TIFF_ENABLED is not defined.
//grids.cpp
if (IsTIFF(header_size, header)) {
#ifdef TIFF_ENABLED
auto set = std::unique_ptr<VerticalShiftGridSet>(
GTiffVGridShiftSet::open(ctx, std::move(fp), actualName));
if (!set)
pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return set;
#else
pj_log(ctx, PJ_LOG_ERROR,
"TIFF grid, but TIFF support disabled in this build");
return nullptr;
#endif
Because I was using VCPKG, this was not possible to amend.
I am fairly new to C++ and have been tinkering with some simple programs to teach myself the basics. I remember a little while ago installing MinGW on my desktop (I think for the C compiler). I decided to go for Cygwin for C++ and it seems to have been working a treat, up until I noticed that it seems to behave differently from the MinGW compiler for this program. I'm probably breaking some coding golden rule, but the reason for this is that Windows CMD uses the MinGW compiler, or I can open the Cygwin shell and use that instead. Variety!
For the program below, I am making notes on the ternary operator and switch statement. I initialize 'a' and 'b', ask for user input, and then use a function to check which is larger.
I then ask for user input again, to over-write the values in 'a' and 'b' to something else. When compiling from Windows CMD, this works fine and I can overwrite with new input, and the #define MAXIMUM and MINIMUM functions work fine on the new values. When I compile on Cygwin, however, after the first 'pause', the program launches past the two std::cin's and just runs MAXIMUM and MINIMUM on the old values of 'a' and 'b'.
Obviously I have tried just creating two new int variables, 'c' and 'd', and then there is no issue. The values are not immutable in any sense that I am aware of (although I don't know much, so I could be wrong).
I wasn't sure if this was something to do with the auto keyword, so I specified the type as int manually.
I also checked the version of both compilers with 'g++ -v' in Cygwin and at the CMD.
#include <iostream>
#include <cstdlib>
#define MAXIMUM(a,b) ((a > b) ? a : b)
#define MINIMUM(a,b) ((a < b) ? a : b)
int ternary_op(int a, int b)
{
char x = 'a';
char y = 'b';
auto result_var = 0;
result_var = a > b ? x : y; //Shorthand if statement with syntax (test_condition) ? (if_true) : (if_false)
return result_var;
}
int main()
{
auto a = 0;
auto b = 0;
auto larger = 0;
auto smaller = 0;
std::cout << "Enter an integer: " << "\n";
std::cin >> a;
std::cout << "Enter another integer: " << "\n";
std::cin >> b;
char greater_var = ternary_op(a,b); //Therefore if condition a > b is satisfied, greater_var is assigned x ('a')
std::cout << greater_var << std::endl;
switch(greater_var){
case 'a':
std::cout << "First integer " << a << " is larger than second, " << b << std::endl;
break;
case 'b':
std::cout << "Second integer " << b << " is larger than first integer, " << a << std::endl;
break;
}
std::cout << system("cmd /c pause") << std::endl;
std::cout << "We can also use defined functions to check equivalency and assign variables based upon the result." << "\n";
std::cout << "Enter an integer: " << std::endl;
std::cin >> a;
std::cout << "Enter another integer: " << std::endl;
std::cin >> b;
larger = MAXIMUM(a,b);
smaller = MINIMUM(a,b);
std::cout << "Larger and smaller numbers determined by defined function: " << larger << ", " << smaller << std::endl;
std::cout << system("cmd /c pause") << std::endl;
return 0;
}
Obviously if I make two new variables, 'c' and 'd', there is no issue. Changing the type to int myself did not change the way the program behaved using Cygwin. Unusually the MinGW version was 8.1.0, while Cygwin was 7.4.0. I'm not sure if this means that it is simply an older version of the same compiler.
Again, I'm very new to this so I'm just quite confused as to why they would behave so differently. I was also under the impression that different compilers were completely different beasts that simply read from the same standard hymn sheet, so to speak.
Just curious as to what is going on here!
Cheers!
I am a classical music fan. My music collection (mp3) has been carefully classified using "composer" (ex. "Surname name (D.O.B-D.O.D"). I frequently get the "artist" from importing the music, ripping or some online data base. Because my mobile music player (Xbox) orders only by "artist", I would like to "swap":
album_artist = artist
artist = composer
and composer would simply remain the same (and same as artist). (Visual Studio 2013, W7, taglib1.9.1):
TagLib::PropertyMap tags = f.file()->properties();
unsigned int longest = 0;
for (TagLib::PropertyMap::ConstIterator i = tags.begin(); i != tags.end(); ++i) {
if (i->first.size() > longest) {
longest = i->first.size();
}
}
cout << "-- TAG (properties) --" << endl;
for (TagLib::PropertyMap::Iterator i = tags.begin(); i != tags.end(); ++i) {
if (i->first == "COMPOSER") {
composer = i->second;
composer_key = i->first;
}
if (i->first == "ARTIST") {
artist.append(i->second);
artist_key = i->first;
}
if (i->first == "ALBUMARTIST") {
album_artist.append(i->second);
album_artist_key = i->first;
}
cout << left << std::setw(longest) << i->first << " - " << '"' << i->second << '"' << endl;
}
if (!tags.replace(album_artist_key, artist))
cout << "album_artist_key is wrong";
else
cout << "replacing " << album_artist_key << " with " << artist << endl;
if (!tags.replace(artist_key, composer))
cout << "artist is wrong";
else
cout << "replacing " << artist_key << " with " << composer << endl;
tag->setArtist(composer.toString());
f.save();
NOTE: this code was modified starting from the tagreader.cpp code found in examples of the library.
This compiles, but after execution, all ID3 tags info disappear (corruption?), as seen by windows explorer. So, I did an experiment and commented out everything that makes any change to the tag. Basically, just open the file (FileRef) and do f.save(). This alone causes the tags to disappear.
Two questions (I think I got this completely wrong ...)
Any reason why f.save would cause a metadata corruption ?
Is the idea I am following (tags.replace and the f.save) correct?
That's not corruption; Windows Explorer just still can't read ID3v2.4 tags, a standard which came out 15 years ago, and is the default in TagLib. TagLib can, however, also write ID3v2.3 tags.
Long story short I am trying to write an application that can check cpu temperatures. Using the libsensors(3) man pages I've been able to at least get the libsensors_version number. As of now, here is my code:
#include <sensors/sensors.h>
#include "SensorData.h"
#include <string>
#include <sstream>
using namespace std;
SensorData::SensorData()
{
sensors_init(NULL);
}
SensorData::~SensorData()
{
sensors_cleanup();
}
string SensorData::GetVersion()
{
ostringstream Converter;
Converter<<"Version: "<<libsensors_version;
return Converter.str();
}
void SensorData::FetchTemp()
{
//sensors_get_value()
}
With the man pages I know that sensors_get_value expects
const sensors_chip_name *name
int subfeat_nr
double *value
to be passed to it. The problem is I have no idea what those are exactly. Just about every function in the documentation has this problem. They all expect vague things I don't know how to supply.
So here is the bulk of the question: Does anyone have any working examples of this library I could look at? Or at the very least does anyone know how to give these functions the values they need?
EDIT:
Since no one seems to know much about this library, does anyone know of a different way to get temperatures?
You can find out how to use the API by browsing the source code. The code for the sensors program isn't too complex to follow.
To get you started, here's a quick function that:
enumerates all the chips
enumerates all their features
prints the values of their readable subfeatures
You can just add it to your existing skeleton class as-is.
(This code is for demo purposes only, not tested thoroughly at all.)
void SensorData::FetchTemp()
{
sensors_chip_name const * cn;
int c = 0;
while ((cn = sensors_get_detected_chips(0, &c)) != 0) {
std::cout << "Chip: " << cn->prefix << "/" << cn->path << std::endl;
sensors_feature const *feat;
int f = 0;
while ((feat = sensors_get_features(cn, &f)) != 0) {
std::cout << f << ": " << feat->name << std::endl;
sensors_subfeature const *subf;
int s = 0;
while ((subf = sensors_get_all_subfeatures(cn, feat, &s)) != 0) {
std::cout << f << ":" << s << ":" << subf->name
<< "/" << subf->number << " = ";
double val;
if (subf->flags & SENSORS_MODE_R) {
int rc = sensors_get_value(cn, subf->number, &val);
if (rc < 0) {
std::cout << "err: " << rc;
} else {
std::cout << val;
}
}
std::cout << std::endl;
}
}
}
}
The Gnome panel Sensors applet works with libsensors (and other backends); the full sources are available from Sourceforge, here: http://sensors-applet.sourceforge.net/index.php?content=source
… in particular, the libsensors plug-in looks fairly legible… I believe this should be a usable gitweb link straight to that code: http://sensors-applet.git.sourceforge.net/git/gitweb.cgi?p=sensors-applet/sensors-applet;a=blob;f=plugins/libsensors/libsensors-plugin.c;h=960c19f4c36902dee4e20b690f2e3dfe6c715279;hb=HEAD
Your code should looks like this:
/* Read /etc/sensors.d to get the names or use code in above post */
std::string chip_name = "CHIP_NAME-*";
/* Here you get the path to the chip you want to read */
int rc;
sensors_chip_name name;
rc = sensors_parse_chip_name(chip_name.c_str(), &name);
/* Check rc != 0 */
/* Here you get the internal structure */
int nr = 0; //Here I silently assume you have only one chip to read
const sensors_chip_name* p_chip;
p_chip = sensors_get_detected_chips(&name, &nr);
/* Check p_chip != 0 */
/* Now you read the value - this you can repeat in some for/while cycle */
double val;
/* Replace the "1" with the feature you want to read */
rc = sensors_get_value(p_chip, 1, &val);
std::cout << "Now I can use sensors library " << val << std::endl;
Hope it helps despite the fact it is not copy/paste solution.
You can obtain the const sensors_chip_name* p_chip; from the code above post as well.
I believe the problem is in fact the const sensors_chip_name MUST be returned and filled by sensors library.
Currently I have the following:
float some_function(){
float percentage = 100;
std::cout << "percentage = " << percentage;
//more code
return 0;
}
which gives the output
percentage = 100
However when I add some std::endl like so:
float some_function(){
float percentage = 100;
std::cout << "percentage = " << percentage << std::endl;
//more code
return 0;
}
This gives the output:
percentage = 1000x6580a8
Adding more endl's just prints out more 0x6580a8's.
What could be causing this? This is compiled with gcc 4.4.3 on Ubuntu 10.04.
The function is written correctly. On my machine ( g++ 4.4.3 on Ubuntu 10.04 ) everything works smoothly.
Are you sure that the error isn't caused by some other part of the code ?
Your code is perfectly valid. I suspect that you could be smashing your stack or heap in some other part of your code as the most likely cause. 0x6580a8 is too short to be an object address. Also, he would never get the same address in two runs of the same program.
What if you tried \n ?
std::cout << "percentage = " << percentage << "\n";
Is this your actual code, or is there a different sort of stream instead of cout?
It's taking the address of the endl manipulator instead of applying it to the stream, which implies that it can't see the matching version of endl for the stream type you're using.
What happens if you use << "\n" << std::flush instead?