test: 增加ocr接口的单元测试

Description:   增加ocr接口的单元测试

Log: no
Change-Id: Ie78bb8f8d2def33ce441857daef52bdc4efa5650
This commit is contained in:
wangcong 2021-06-28 21:17:18 +08:00
parent c2f16bd20e
commit facb87f672
8 changed files with 5847 additions and 4 deletions

280
3rdparty/stub_linux/addr_any.h vendored Executable file
View File

@ -0,0 +1,280 @@
#ifndef __ADDR_ANY_H__
#define __ADDR_ANY_H__
//linux
#include <regex.h>
#include <cxxabi.h>
//c
#include <cinttypes>
#include <cstdio>
#include <cstdlib>
//c++
#include <string>
#include <map>
//project
#include "elfio.hpp"
class AddrAny
{
public:
AddrAny()
{
m_init = get_exe_pathname(m_fullname);
m_baseaddr = 0;
}
AddrAny(std::string libname)
{
m_init = get_lib_pathname_and_baseaddr(libname, m_fullname, m_baseaddr);
}
int get_local_func_addr_symtab(std::string func_name_regex_str, std::map<std::string,void*>& result)
{
return get_func_addr(SHT_SYMTAB, STB_LOCAL, func_name_regex_str, result);
}
int get_global_func_addr_symtab(std::string func_name_regex_str, std::map<std::string,void*>& result)
{
return get_func_addr(SHT_SYMTAB, STB_GLOBAL, func_name_regex_str, result);
}
int get_weak_func_addr_symtab(std::string func_name_regex_str, std::map<std::string,void*>& result)
{
return get_func_addr(SHT_SYMTAB, STB_WEAK, func_name_regex_str, result);
}
int get_global_func_addr_dynsym( std::string func_name_regex_str, std::map<std::string,void*>& result)
{
return get_func_addr(SHT_DYNSYM, STB_GLOBAL, func_name_regex_str, result);
}
int get_weak_func_addr_dynsym(std::string func_name_regex_str, std::map<std::string,void*>& result)
{
return get_func_addr(SHT_DYNSYM, STB_WEAK, func_name_regex_str, result);
}
private:
bool demangle(std::string& s, std::string& name) {
int status;
char* pname = abi::__cxa_demangle(s.c_str(), 0, 0, &status);
if (status != 0)
{
switch(status)
{
case -1: name = "memory allocation error"; break;
case -2: name = "invalid name given"; break;
case -3: name = "internal error: __cxa_demangle: invalid argument"; break;
default: name = "unknown error occured"; break;
}
return false;
}
name = pname;
free(pname);
return true;
}
bool get_exe_pathname( std::string& name)
{
char line[512];
FILE *fp;
uintptr_t base_addr;
char perm[5];
unsigned long offset;
int pathname_pos;
char *pathname;
size_t pathname_len;
int match = 0;
if(NULL == (fp = fopen("/proc/self/maps", "r")))
{
return false;
}
while(fgets(line, sizeof(line), fp))
{
if(sscanf(line, "%" PRIxPTR "-%*lx %4s %lx %*x:%*x %*d%n", &base_addr, perm, &offset, &pathname_pos) != 3) continue;
if(0 != offset) continue;
//get pathname
while(isspace(line[pathname_pos]) && pathname_pos < (int)(sizeof(line) - 1))
pathname_pos += 1;
if(pathname_pos >= (int)(sizeof(line) - 1)) continue;
pathname = line + pathname_pos;
pathname_len = strlen(pathname);
if(0 == pathname_len) continue;
if(pathname[pathname_len - 1] == '\n')
{
pathname[pathname_len - 1] = '\0';
pathname_len -= 1;
}
if(0 == pathname_len) continue;
if('[' == pathname[0]) continue;
name = pathname;
match = 1;
break;
}
fclose(fp);
if(0 == match)
{
return false;
}
else
{
return true;
}
}
bool get_lib_pathname_and_baseaddr(std::string pathname_regex_str, std::string& name, unsigned long& addr)
{
char line[512];
FILE *fp;
uintptr_t base_addr;
char perm[5];
unsigned long offset;
int pathname_pos;
char *pathname;
size_t pathname_len;
int match;
regex_t pathname_regex;
regcomp(&pathname_regex, pathname_regex_str.c_str(), 0);
if(NULL == (fp = fopen("/proc/self/maps", "r")))
{
return false;
}
while(fgets(line, sizeof(line), fp))
{
if(sscanf(line, "%" PRIxPTR "-%*lx %4s %lx %*x:%*x %*d%n", &base_addr, perm, &offset, &pathname_pos) != 3) continue;
//check permission
if(perm[0] != 'r') continue;
if(perm[3] != 'p') continue; //do not touch the shared memory
//check offset
//
//We are trying to find ELF header in memory.
//It can only be found at the beginning of a mapped memory regions
//whose offset is 0.
if(0 != offset) continue;
//get pathname
while(isspace(line[pathname_pos]) && pathname_pos < (int)(sizeof(line) - 1))
pathname_pos += 1;
if(pathname_pos >= (int)(sizeof(line) - 1)) continue;
pathname = line + pathname_pos;
pathname_len = strlen(pathname);
if(0 == pathname_len) continue;
if(pathname[pathname_len - 1] == '\n')
{
pathname[pathname_len - 1] = '\0';
pathname_len -= 1;
}
if(0 == pathname_len) continue;
if('[' == pathname[0]) continue;
//check pathname
//if we need to hook this elf?
match = 0;
if(0 == regexec(&pathname_regex, pathname, 0, NULL, 0))
{
match = 1;
name = pathname;
addr = (unsigned long)base_addr;
break;
}
if(0 == match) continue;
}
fclose(fp);
if(0 == match)
{
return false;
}
else
{
return true;
}
}
int get_func_addr(unsigned int ttype, unsigned int stype, std::string& func_name_regex_str, std::map<std::string,void*>& result)
{
// Create an elfio reader
ELFIO::elfio reader;
int count = 0;
regex_t pathname_regex;
if(!m_init)
{
return -1;
}
regcomp(&pathname_regex, func_name_regex_str.c_str(), 0);
// Load ELF data
if(!reader.load(m_fullname.c_str()))
{
return -1;
}
ELFIO::Elf_Half sec_num = reader.sections.size();
for(int i = 0; i < sec_num; ++i)
{
ELFIO::section* psec = reader.sections[i];
// Check section type
if(psec->get_type() == ttype)
{
const ELFIO::symbol_section_accessor symbols( reader, psec );
for ( unsigned int j = 0; j < symbols.get_symbols_num(); ++j )
{
std::string name;
std::string name_mangle;
ELFIO::Elf64_Addr value;
ELFIO::Elf_Xword size;
unsigned char bind;
unsigned char type;
ELFIO::Elf_Half section_index;
unsigned char other;
// Read symbol properties
symbols.get_symbol( j, name, value, size, bind, type, section_index, other );
if(type == STT_FUNC && bind == stype)
{
bool ret = demangle(name,name_mangle);
if(ret == true)
{
if (0 == regexec(&pathname_regex, name_mangle.c_str(), 0, NULL, 0))
{
result.insert ( std::pair<std::string,void *>(name_mangle,(void*)(value + m_baseaddr)));
count++;
}
}
else
{
if (0 == regexec(&pathname_regex, name.c_str(), 0, NULL, 0))
{
result.insert ( std::pair<std::string,void *>(name,(void*)(value + m_baseaddr)));
count++;
}
}
}
}
break;
}
}
return count;
}
private:
bool m_init;
std::string m_name;
std::string m_fullname;
unsigned long m_baseaddr;
};
#endif

177
3rdparty/stub_linux/addr_pri.h vendored Executable file
View File

@ -0,0 +1,177 @@
#ifndef __ADDR_PRI_H__
#define __ADDR_PRI_H__
#include <utility>
#include <type_traits>
//base on C++11
/**********************************************************
access private function
**********************************************************/
namespace std {
template <bool B, class T = void>
using enable_if_t = typename enable_if<B, T>::type;
template <class T>
using remove_reference_t = typename remove_reference<T>::type;
} // std
// Unnamed namespace is used to avoid duplicate symbols if the macros are used
namespace {
namespace private_access_detail {
// @tparam TagType, used to declare different "get" funciton overloads for
// different members/statics
template <typename PtrType, PtrType PtrValue, typename TagType>
struct private_access {
// Normal lookup cannot find in-class defined (inline) friend functions.
friend PtrType get(TagType) { return PtrValue; }
};
} // namespace private_access_detail
} // namespace
// Used macro naming conventions:
// The "namespace" of this macro library is PRIVATE_ACCESS, i.e. all
// macro here has this prefix.
// All implementation macro, which are not meant to be used directly have the
// PRIVATE_ACCESS_DETAIL prefix.
// Some macros have the ABCD_IMPL form, which means they contain the
// implementation details for the specific ABCD macro.
#define PRIVATE_ACCESS_DETAIL_CONCATENATE_IMPL(x, y) x##y
#define PRIVATE_ACCESS_DETAIL_CONCATENATE(x, y) \
PRIVATE_ACCESS_DETAIL_CONCATENATE_IMPL(x, y)
// @param PtrTypeKind E.g if we have "class A", then it can be "A::*" in case of
// members, or it can be "*" in case of statics.
#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, \
PtrTypeKind) \
namespace { \
namespace private_access_detail { \
/* Tag type, used to declare different get funcitons for different \
* members \
*/ \
struct Tag {}; \
/* Explicit instantiation */ \
template struct private_access<decltype(&Class::Name), &Class::Name, \
Tag>; \
/* We can build the PtrType only with two aliases */ \
/* E.g. using PtrType = int(int) *; would be illformed */ \
using PRIVATE_ACCESS_DETAIL_CONCATENATE(Alias_, Tag) = Type; \
using PRIVATE_ACCESS_DETAIL_CONCATENATE(PtrType_, Tag) = \
PRIVATE_ACCESS_DETAIL_CONCATENATE(Alias_, Tag) PtrTypeKind; \
/* Declare the friend function, now it is visible in namespace scope. \
* Note, \
* we could declare it inside the Tag type too, in that case ADL would \
* find \
* the declaration. By choosing to declare it here, the Tag type remains \
* a \
* simple tag type, it has no other responsibilities. */ \
PRIVATE_ACCESS_DETAIL_CONCATENATE(PtrType_, Tag) get(Tag); \
} \
}
#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FIELD(Tag, Class, Type, Name) \
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, Class::*) \
namespace { \
namespace access_private_field { \
Type &Class##Name(Class &&t) { return t.*get(private_access_detail::Tag{}); } \
Type &Class##Name(Class &t) { return t.*get(private_access_detail::Tag{}); } \
/* The following usings are here to avoid duplicate const qualifier \
* warnings \
*/ \
using PRIVATE_ACCESS_DETAIL_CONCATENATE(X, Tag) = Type; \
using PRIVATE_ACCESS_DETAIL_CONCATENATE(Y, Tag) = \
const PRIVATE_ACCESS_DETAIL_CONCATENATE(X, Tag); \
PRIVATE_ACCESS_DETAIL_CONCATENATE(Y, Tag) & Class##Name(const Class &t) {\
return t.*get(private_access_detail::Tag{}); \
} \
} \
}
#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FUN(Tag, Class, Type, Name) \
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, Class::*) \
namespace { \
namespace call_private_fun { \
/* We do perfect forwarding, but we want to restrict the overload set \
* only for objects which have the type Class. */ \
template <typename Obj, \
std::enable_if_t<std::is_same<std::remove_reference_t<Obj>, \
Class>::value> * = nullptr, \
typename... Args> \
auto Class##Name(Obj &&o, Args &&... args) -> decltype( \
(std::forward<Obj>(o).* \
get(private_access_detail::Tag{}))(std::forward<Args>(args)...)) { \
return (std::forward<Obj>(o).*get(private_access_detail::Tag{}))( \
std::forward<Args>(args)...); \
} \
} \
namespace get_private_fun { \
auto Class##Name() -> decltype( \
get(private_access_detail::Tag{})) { \
return (get(private_access_detail::Tag{})); \
} \
} \
}
#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FIELD(Tag, Class, Type, \
Name) \
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, *) \
namespace { \
namespace access_private_static_field { \
namespace Class { \
Type &Class##Name() { return *get(private_access_detail::Tag{}); } \
} \
} \
}
#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FUN(Tag, Class, Type, \
Name) \
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, *) \
namespace { \
namespace call_private_static_fun { \
namespace Class { \
template <typename... Args> \
auto Class##Name(Args &&... args) -> decltype( \
get(private_access_detail::Tag{})(std::forward<Args>(args)...)) { \
return get(private_access_detail::Tag{})( \
std::forward<Args>(args)...); \
} \
} \
} \
namespace get_private_static_fun { \
namespace Class { \
auto Class##Name() -> decltype(get(private_access_detail::Tag{})) { \
return get(private_access_detail::Tag{}); \
} \
} \
} \
}
#define PRIVATE_ACCESS_DETAIL_UNIQUE_TAG \
PRIVATE_ACCESS_DETAIL_CONCATENATE(PrivateAccessTag, __COUNTER__)
#define ACCESS_PRIVATE_FIELD(Class, Type, Name) \
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FIELD(PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, \
Class, Type, Name)
#define ACCESS_PRIVATE_FUN(Class, Type, Name) \
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FUN(PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, \
Class, Type, Name)
#define ACCESS_PRIVATE_STATIC_FIELD(Class, Type, Name) \
Type Class::Name; \
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FIELD( \
PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, Class, Type, Name)
#define ACCESS_PRIVATE_STATIC_FUN(Class, Type, Name) \
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FUN( \
PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, Class, Type, Name)
#endif

4888
3rdparty/stub_linux/elfio.hpp vendored Executable file

File diff suppressed because it is too large Load Diff

281
3rdparty/stub_linux/stub.h vendored Executable file
View File

@ -0,0 +1,281 @@
#ifndef __STUB_H__
#define __STUB_H__
#ifdef _WIN32
//windows
#include <windows.h>
#else
//linux
#include <unistd.h>
#include <sys/mman.h>
#endif
//c
#include <cstddef>
#include <cstring>
//c++
#include <map>
#define ADDR(CLASS_NAME,MEMBER_NAME) (&CLASS_NAME::MEMBER_NAME)
/**********************************************************
replace function
**********************************************************/
#if defined(__aarch64__) || defined(_M_ARM64)
#define CODESIZE 16U
#define CODESIZE_MIN 16U
#define CODESIZE_MAX CODESIZE
// ldr x9, +8
// br x9
// addr
#define REPLACE_FAR(t, fn, fn_stub)\
((uint32_t*)fn)[0] = 0x58000040 | 9;\
((uint32_t*)fn)[1] = 0xd61f0120 | (9 << 5);\
*(long long *)(fn + 8) = (long long )fn_stub;
#define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub)
#elif defined(__arm__) || defined(_M_ARM)
#define CODESIZE 8U
#define CODESIZE_MIN 8U
#define CODESIZE_MAX CODESIZE
// ldr pc, [pc, #-4]
#define REPLACE_FAR(t, fn, fn_stub)\
((uint32_t*)fn)[0] = 0xe51ff004;\
((uint32_t*)fn)[1] = (uint32_t)fn_stub;
#define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub)
#elif defined(__thumb__) || defined(_M_THUMB)
#error "Thumb is not supported"
#else //__i386__ _x86_64__
#define CODESIZE 13U
#define CODESIZE_MIN 5U
#define CODESIZE_MAX CODESIZE
//13 byte(jmp m16:64)
//movabs $0x102030405060708,%r11
//jmpq *%r11
#define REPLACE_FAR(t, fn, fn_stub)\
*fn = 0x49;\
*(fn + 1) = 0xbb;\
*(long long *)(fn + 2) = (long long)fn_stub;\
*(fn + 10) = 0x41;\
*(fn + 11) = 0xff;\
*(fn + 12) = 0xe3;
//5 byte(jmp rel32)
#define REPLACE_NEAR(t, fn, fn_stub)\
*fn = 0xE9;\
*(int *)(fn + 1) = (int)(fn_stub - fn - CODESIZE_MIN);
#endif
struct func_stub
{
char *fn;
unsigned char code_buf[CODESIZE];
bool far_jmp;
};
class Stub
{
public:
Stub()
{
#ifdef _WIN32
SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info);
m_pagesize = sys_info.dwPageSize;
#else
m_pagesize = sysconf(_SC_PAGE_SIZE);
#endif
if (m_pagesize < 0)
{
m_pagesize = 4096;
}
}
~Stub()
{
std::map<char*,func_stub*>::iterator iter;
struct func_stub *pstub;
for(iter=m_result.begin(); iter != m_result.end(); iter++)
{
pstub = iter->second;
#ifdef _WIN32
DWORD lpflOldProtect;
if(0 != VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect))
#else
if (0 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC))
#endif
{
if(pstub->far_jmp)
{
std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MAX);
}
else
{
std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MIN);
}
#ifdef _WIN32
VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect);
#else
mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC);
#endif
}
iter->second = NULL;
delete pstub;
}
return;
}
template<typename T,typename S>
void set(T addr, S addr_stub)
{
char * fn;
char * fn_stub;
fn = addrof(addr);
fn_stub = addrof(addr_stub);
struct func_stub *pstub;
pstub = new func_stub;
//start
pstub->fn = fn;
if(distanceof(fn, fn_stub))
{
pstub->far_jmp = true;
std::memcpy(pstub->code_buf, fn, CODESIZE_MAX);
}
else
{
pstub->far_jmp = false;
std::memcpy(pstub->code_buf, fn, CODESIZE_MIN);
}
#ifdef _WIN32
DWORD lpflOldProtect;
if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect))
#else
if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC))
#endif
{
throw("stub set memory protect to w+r+x faild");
}
if(pstub->far_jmp)
{
REPLACE_FAR(this, fn, fn_stub);
}
else
{
REPLACE_NEAR(this, fn, fn_stub);
}
#ifdef _WIN32
if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect))
#else
if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC))
#endif
{
throw("stub set memory protect to r+x failed");
}
m_result.insert(std::pair<char*,func_stub*>(fn,pstub));
return;
}
template<typename T>
void reset(T addr)
{
char * fn;
fn = addrof(addr);
std::map<char*,func_stub*>::iterator iter = m_result.find(fn);
if (iter == m_result.end())
{
return;
}
struct func_stub *pstub;
pstub = iter->second;
#ifdef _WIN32
DWORD lpflOldProtect;
if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect))
#else
if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC))
#endif
{
throw("stub reset memory protect to w+r+x faild");
}
if(pstub->far_jmp)
{
std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MAX);
}
else
{
std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MIN);
}
#ifdef _WIN32
if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect))
#else
if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC))
#endif
{
throw("stub reset memory protect to r+x failed");
}
m_result.erase(iter);
delete pstub;
return;
}
private:
char *pageof(char* addr)
{
#ifdef _WIN32
return (char *)((unsigned long long)addr & ~(m_pagesize - 1));
#else
return (char *)((unsigned long)addr & ~(m_pagesize - 1));
#endif
}
template<typename T>
char* addrof(T addr)
{
union
{
T _s;
char* _d;
}ut;
ut._s = addr;
return ut._d;
}
bool distanceof(char* addr, char* addr_stub)
{
std::ptrdiff_t diff = addr_stub >= addr ? addr_stub - addr : addr - addr_stub;
if((sizeof(addr) > 4) && (((diff >> 31) - 1) > 0))
{
return true;
}
return false;
}
private:
#ifdef _WIN32
//LLP64
long long m_pagesize;
#else
//LP64
long m_pagesize;
#endif
std::map<char*, func_stub*> m_result;
};
#endif

View File

@ -134,6 +134,7 @@ if(DOTEST)
include_directories(./src/service) include_directories(./src/service)
include_directories(./src/tessocrutils) include_directories(./src/tessocrutils)
include_directories(./src/view) include_directories(./src/view)
include_directories(${PROJECT_SOURCE_DIR}/3rdparty/stub_linux/)
#使tesseracttesseract #使tesseracttesseract
# include_directories(/usr/include/leptonica) # include_directories(/usr/include/leptonica)
# include_directories(${PROJECT_SOURCE_DIR}/3rdparty/tesseract_ocr/tesseract/include) # include_directories(${PROJECT_SOURCE_DIR}/3rdparty/tesseract_ocr/tesseract/include)
@ -156,6 +157,7 @@ if(DOTEST)
aux_source_directory(src/view allTestSource) aux_source_directory(src/view allTestSource)
aux_source_directory(tests allTestSource) aux_source_directory(tests allTestSource)
aux_source_directory(tests/tessocrutils allTestSource) aux_source_directory(tests/tessocrutils allTestSource)
aux_source_directory(${PROJECT_SOURCE_DIR}/3rdparty/stub_linux/ allTestSource)
#使tesseracttesseract #使tesseracttesseract
# aux_source_directory(3rdparty/tesseract_ocr/tesseract/src/api allTestSource) # aux_source_directory(3rdparty/tesseract_ocr/tesseract/src/api allTestSource)
# #aux_source_directory(3rdparty/tesseract_ocr/tesseract/src/arch allSource) # #aux_source_directory(3rdparty/tesseract_ocr/tesseract/src/arch allSource)

View File

@ -125,7 +125,7 @@ RecognitionResult TessOcrUtils::getRecogitionResult(const QString &imagePath,con
return t_result; return t_result;
} }
//获取识别结果 //获取识别结果
return getRecogitionResult(p_image,resultType); return getRecognizeResult(p_image,resultType);
} }
//传入待识别图片的路径,获取纯字符串的识别结果 //传入待识别图片的路径,获取纯字符串的识别结果
@ -171,7 +171,7 @@ RecognitionResult TessOcrUtils::getRecogitionResult(QImage *image, const ResultT
//p_image->colormap->n; //p_image->colormap->n;
p_image->data = reinterpret_cast<l_uint32*>(image->bits()); p_image->data = reinterpret_cast<l_uint32*>(image->bits());
//获取识别结果 //获取识别结果
return getRecogitionResult(p_image,resultType); return getRecognizeResult(p_image,resultType);
} }
//传入待识别图片,获取纯字符串的识别结果 //传入待识别图片,获取纯字符串的识别结果
@ -231,7 +231,7 @@ bool TessOcrUtils::setLanguagesPath(const QString langsPath)
} }
//获取识别结果 //获取识别结果
RecognitionResult TessOcrUtils::getRecogitionResult(Pix * image,ResultType resultType) RecognitionResult TessOcrUtils::getRecognizeResult(Pix * image,ResultType resultType)
{ {
QString errorMessage = ""; QString errorMessage = "";
ErrorCode errorCode = ErrorCode::UNKNOWN; ErrorCode errorCode = ErrorCode::UNKNOWN;

View File

@ -228,7 +228,7 @@ private :
* @param * @param
* @return * @return
*/ */
RecognitionResult getRecogitionResult(Pix * image,ResultType resultType); RecognitionResult getRecognizeResult(Pix * image,ResultType resultType);
/** /**
* @brief ,使 * @brief ,使

View File

@ -0,0 +1,215 @@
/*
* Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd.
*
* Author: wangcong <wangcong@uniontech.com>
*
* Maintainer: wangcong <wangcong@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../../src/tessocrutils/tessocrutils.h"
#include "stub.h"
#include "addr_pri.h"
#include <QDir>
#include <QStandardPaths>
#include <gtest/gtest.h>
class TessOcrUtilsTest:public testing::Test{
public:
Stub stub;
TessOcrUtils *m_tessOCrUtils = nullptr;
virtual void SetUp() override{
m_tessOCrUtils = TessOcrUtils::instance();
std::cout << "start TessOcrUtilsTest" << std::endl;
}
virtual void TearDown() override{
std::cout << "end TessOcrUtilsTest" << std::endl;
}
};
ACCESS_PRIVATE_FUN(TessOcrUtils, bool(const QString), setLanguagesPath);
ACCESS_PRIVATE_FUN(TessOcrUtils, bool(ResultType), isExistsResultType);
ACCESS_PRIVATE_FUN(TessOcrUtils, QString(Languages), getLangStr);
ACCESS_PRIVATE_FUN(TessOcrUtils, Languages(), getSystemLang);
ACCESS_PRIVATE_FUN(TessOcrUtils, QString(), getLanguages);
ACCESS_PRIVATE_FUN(TessOcrUtils, RecognitionResult(Pix*, ResultType), getRecognizeResult);
ACCESS_PRIVATE_FUN(TessOcrUtils, void(ErrorCode, const QString,const ResultType,RecognitionResult &), setResult);
TEST_F(TessOcrUtilsTest, tessOcrUtils)
{
EXPECT_NE(nullptr, m_tessOCrUtils);
}
TEST_F(TessOcrUtilsTest, getRecogitionResultImagePathAndResultType)
{
//QString imagePath = "/media/wangcong/workspace/wangcong/workspace/qt_workspace/project/deepin-ocr/assets/testocr.png";
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
ResultType resultType = ResultType::RESULT_STRING;
RecognitionResult recognitionResult = m_tessOCrUtils->getRecogitionResult(imagePath,resultType);
EXPECT_EQ(true, recognitionResult.flag);
EXPECT_EQ("", recognitionResult.message);
EXPECT_EQ(ErrorCode::OK, recognitionResult.errorCode);
EXPECT_EQ(resultType, recognitionResult.resultType);
//EXPECT_NE("", recognitionResult.result);
}
TEST_F(TessOcrUtilsTest, getRecogitionResult2ImagePath)
{
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
RecognitionResult recognitionResult = m_tessOCrUtils->getRecogitionResult(imagePath);
recognitionResult = m_tessOCrUtils->getRecogitionResult(imagePath);
EXPECT_EQ(true, recognitionResult.flag);
EXPECT_EQ("", recognitionResult.message);
EXPECT_EQ(ErrorCode::OK, recognitionResult.errorCode);
EXPECT_EQ(ResultType::RESULT_STRING, recognitionResult.resultType);
//EXPECT_NE("", recognitionResult.result);
}
TEST_F(TessOcrUtilsTest, getRecogitionResultImageAndResultType)
{
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
ResultType resultType = ResultType::RESULT_STRING;
QImage* t_image = new QImage(imagePath);
RecognitionResult recognitionResult = TessOcrUtils::instance()->getRecogitionResult(t_image,resultType);
EXPECT_EQ(true, recognitionResult.flag);
EXPECT_EQ("", recognitionResult.message);
EXPECT_EQ(ErrorCode::OK, recognitionResult.errorCode);
EXPECT_EQ(resultType, recognitionResult.resultType);
//EXPECT_NE("", recognitionResult.result);
}
TEST_F(TessOcrUtilsTest, getRecogitionResultImage)
{
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
QImage* t_image = new QImage(imagePath);
RecognitionResult recognitionResult = TessOcrUtils::instance()->getRecogitionResult(t_image);
EXPECT_EQ(true, recognitionResult.flag);
EXPECT_EQ("", recognitionResult.message);
EXPECT_EQ(ErrorCode::OK, recognitionResult.errorCode);
EXPECT_EQ(ResultType::RESULT_STRING, recognitionResult.resultType);
//EXPECT_NE("", recognitionResult.result);
}
TEST_F(TessOcrUtilsTest, isRunning)
{
EXPECT_EQ(false, m_tessOCrUtils->isRunning());
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
ResultType resultType = ResultType::RESULT_STRING;
RecognitionResult recognitionResult = m_tessOCrUtils->getRecogitionResult(imagePath,resultType);
EXPECT_EQ(false, m_tessOCrUtils->isRunning());
}
TEST_F(TessOcrUtilsTest, getRecognizeResult)
{
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
QImage* image = new QImage(imagePath);
ResultType resultType = ResultType::RESULT_STRING;
Pix *p_image;
p_image = pixCreate(image->width(), image->height(), image->depth());
p_image->w = static_cast<l_uint32>(image->width());
p_image->h = static_cast<l_uint32>(image->height());
p_image->d = static_cast<l_uint32>(image->depth());
p_image->spp = 3;
p_image->wpl = static_cast<l_uint32>(image->width());
p_image->refcount = 1;
p_image->xres = 0;
p_image->yres = 0;
p_image->informat = 0;
p_image->special = 0;
p_image->text = nullptr;
p_image->colormap = nullptr;
p_image->data = reinterpret_cast<l_uint32*>(image->bits());
RecognitionResult recognitionResult = call_private_fun::TessOcrUtilsgetRecognizeResult(*m_tessOCrUtils,p_image,resultType);
EXPECT_EQ(true, recognitionResult.flag);
EXPECT_EQ("", recognitionResult.message);
EXPECT_EQ(ErrorCode::OK, recognitionResult.errorCode);
EXPECT_EQ(ResultType::RESULT_STRING, recognitionResult.resultType);
}
TEST_F(TessOcrUtilsTest, setLanguagesPath)
{
const QString TessDataPath = "/usr/share/deepin-ocr/tesslangs";
bool flag = call_private_fun::TessOcrUtilssetLanguagesPath(*m_tessOCrUtils,TessDataPath);
//EXPECT_EQ(true, flag);
}
TEST_F(TessOcrUtilsTest, isExistsResultType)
{
const QString TessDataPath = "/usr/share/deepin-ocr/tesslangs";
bool flag = call_private_fun::TessOcrUtilsisExistsResultType(*m_tessOCrUtils,ResultType::RESULT_STRING);
//EXPECT_EQ(true, flag);
flag = call_private_fun::TessOcrUtilsisExistsResultType(*m_tessOCrUtils,ResultType::RESULT_HTML);
//EXPECT_EQ(true, flag);
flag = call_private_fun::TessOcrUtilsisExistsResultType(*m_tessOCrUtils,ResultType::UNKNOWN_TYPE);
//EXPECT_EQ(false, flag);
}
TEST_F(TessOcrUtilsTest, getLangStr)
{
QString lang = call_private_fun::TessOcrUtilsgetLangStr(*m_tessOCrUtils,Languages::ENG);
EXPECT_EQ("eng", lang);
lang = call_private_fun::TessOcrUtilsgetLangStr(*m_tessOCrUtils,Languages::CHI_SIM);
EXPECT_EQ("chi_sim", lang);
lang = call_private_fun::TessOcrUtilsgetLangStr(*m_tessOCrUtils,Languages::CHI_TRA);
EXPECT_EQ("chi_tra", lang);
}
TEST_F(TessOcrUtilsTest, getSystemLang)
{
Languages lang = call_private_fun::TessOcrUtilsgetSystemLang(*m_tessOCrUtils);
EXPECT_NE(Languages::UNKNOWN_LAN, lang);
}
TEST_F(TessOcrUtilsTest, getLanguages)
{
QString lang = call_private_fun::TessOcrUtilsgetLanguages(*m_tessOCrUtils);
EXPECT_NE("", lang);
}
TEST_F(TessOcrUtilsTest, setResult)
{
RecognitionResult result ;
call_private_fun::TessOcrUtilssetResult(*m_tessOCrUtils,ErrorCode::UNKNOWN,"test",ResultType::RESULT_STRING,result);
EXPECT_EQ(false, result.flag);
EXPECT_EQ(ErrorCode::UNKNOWN, result.errorCode);
EXPECT_EQ("test", result.message);
EXPECT_EQ(ResultType::RESULT_STRING, result.resultType);
EXPECT_EQ("", result.result);
}