23 #if defined(USE_OPENCL)
27 #include <allheaders.h>
44 , estimated_res_(300) {
59 return pix_ ==
nullptr;
71 int bytes_per_pixel,
int bytes_per_line) {
72 int bpp = bytes_per_pixel * 8;
76 Image pix = pixCreate(width, height, bpp == 24 ? 32 : bpp);
77 l_uint32 *data = pixGetData(pix);
78 int wpl = pixGetWpl(pix);
81 for (
int y = 0; y < height; ++y, data += wpl, imagedata += bytes_per_line) {
82 for (
int x = 0; x < width; ++x) {
83 if (imagedata[x / 8] & (0x80 >> (x % 8))) {
84 CLEAR_DATA_BIT(data, x);
86 SET_DATA_BIT(data, x);
94 for (
int y = 0; y < height; ++y, data += wpl, imagedata += bytes_per_line) {
95 for (
int x = 0; x < width; ++x) {
96 SET_DATA_BYTE(data, x, imagedata[x]);
103 for (
int y = 0; y < height; ++y, imagedata += bytes_per_line) {
104 for (
int x = 0; x < width; ++x, ++data) {
105 SET_DATA_BYTE(data, COLOR_RED, imagedata[3 * x]);
106 SET_DATA_BYTE(data, COLOR_GREEN, imagedata[3 * x + 1]);
107 SET_DATA_BYTE(data, COLOR_BLUE, imagedata[3 * x + 2]);
114 for (
int y = 0; y < height; ++y, imagedata += bytes_per_line, data += wpl) {
115 for (
int x = 0; x < width; ++x) {
116 data[x] = (imagedata[x * 4] << 24) | (imagedata[x * 4 + 1] << 16) |
117 (imagedata[x * 4 + 2] << 8) | imagedata[x * 4 + 3];
123 tprintf(
"Cannot convert RAW image to Pix with bpp = %d\n", bpp);
158 if (
pix_ !=
nullptr) {
167 if (pixGetColormap(src)) {
168 Image tmp = pixRemoveColormap(src, REMOVE_CMAP_BASED_ON_SRC);
169 depth = pixGetDepth(tmp);
170 if (depth > 1 && depth < 8) {
171 pix_ = pixConvertTo8(tmp,
false);
176 }
else if (depth > 1 && depth < 8) {
177 pix_ = pixConvertTo8(src,
false);
181 depth = pixGetDepth(
pix_);
192 Image pix_binary =
nullptr;
193 Image pix_thresholds =
nullptr;
199 pix_binary = original.
copy();
201 return std::make_tuple(
true,
nullptr, pix_binary,
nullptr);
208 l_int32 pix_w, pix_h;
209 pixGetDimensions(pix_grey, &pix_w, &pix_h,
nullptr);
211 bool thresholding_debug;
213 if (thresholding_debug) {
214 tprintf(
"\nimage width: %d height: %d ppi: %d\n", pix_w, pix_h,
yres_);
219 double window_size_factor;
221 window_size = window_size_factor *
yres_;
222 window_size = std::max(7, window_size);
223 window_size = std::min(pix_w < pix_h ? pix_w - 3 : pix_h - 3, window_size);
224 int half_window_size = window_size / 2;
229 nx = std::max(1, (pix_w + 125) / 250);
230 ny = std::max(1, (pix_h + 125) / 250);
231 auto xrat = pix_w / nx;
232 auto yrat = pix_h / ny;
233 if (xrat < half_window_size + 2) {
234 nx = pix_w / (half_window_size + 2);
236 if (yrat < half_window_size + 2) {
237 ny = pix_h / (half_window_size + 2);
242 kfactor = std::max(0.0, kfactor);
244 if (thresholding_debug) {
245 tprintf(
"window size: %d kfactor: %.3f nx:%d ny: %d\n", window_size, kfactor, nx, ny);
248 r = pixSauvolaBinarizeTiled(pix_grey, half_window_size, kfactor, nx, ny,
249 (PIX**)pix_thresholds,
253 double tile_size_factor;
255 tile_size = tile_size_factor *
yres_;
256 tile_size = std::max(16, tile_size);
259 double smooth_size_factor;
261 &smooth_size_factor);
262 smooth_size_factor = std::max(0.0, smooth_size_factor);
263 smooth_size = smooth_size_factor *
yres_;
264 int half_smooth_size = smooth_size / 2;
266 double score_fraction;
269 if (thresholding_debug) {
270 tprintf(
"tile size: %d smooth_size: %d score_fraction: %.2f\n", tile_size, smooth_size, score_fraction);
273 r = pixOtsuAdaptiveThreshold(pix_grey, tile_size, tile_size,
274 half_smooth_size, half_smooth_size,
276 (PIX**)pix_thresholds,
281 return std::make_tuple(ok, pix_grey, pix_binary, pix_thresholds);
297 *pix = original.
copy();
317 int width = pixGetWidth(pix_grey);
318 int height = pixGetHeight(pix_grey);
319 std::vector<int> thresholds;
320 std::vector<int> hi_values;
321 OtsuThreshold(pix_grey, 0, 0, width, height, thresholds, hi_values);
323 Image pix_thresholds = pixCreate(width, height, 8);
324 int threshold = thresholds[0] > 0 ? thresholds[0] : 128;
325 pixSetAllArbitrary(pix_thresholds, threshold);
326 return pix_thresholds;
346 Image cropped = pixClipRectangle(
pix_, box,
nullptr);
358 int depth = pixGetDepth(pix);
361 auto tmp = pixConvert24To32(pix);
365 auto result = pixConvertTo8(pix,
false);
374 std::vector<int> thresholds;
375 std::vector<int> hi_values;
378 thresholds, hi_values);
382 if (num_channels == 4 && od.selectedDeviceIsOpenCL() &&
rect_top_ == 0 &&
rect_left_ == 0) {
383 od.ThresholdRectToPixOCL((
unsigned char *)pixGetData(src_pix), num_channels,
384 pixGetWpl(src_pix) * 4, &thresholds[0], &hi_values[0], out_pix ,
399 const std::vector<int> &hi_values,
Image *pix)
const {
401 uint32_t *pixdata = pixGetData(*pix);
402 int wpl = pixGetWpl(*pix);
403 int src_wpl = pixGetWpl(src_pix);
404 uint32_t *srcdata = pixGetData(src_pix);
405 pixSetXRes(*pix, pixGetXRes(src_pix));
406 pixSetYRes(*pix, pixGetYRes(src_pix));
408 const uint32_t *linedata = srcdata + (y +
rect_top_) * src_wpl;
409 uint32_t *pixline = pixdata + y * wpl;
411 bool white_result =
true;
412 for (
int ch = 0; ch < num_channels; ++ch) {
413 int pixel = GET_DATA_BYTE(linedata, (x +
rect_left_) * num_channels + ch);
414 if (hi_values[ch] >= 0 && (pixel > thresholds[ch]) == (hi_values[ch] == 0)) {
415 white_result =
false;
420 CLEAR_DATA_BIT(pixline, x);
422 SET_DATA_BIT(pixline, x);
void tprintf(const char *format,...)
int OtsuThreshold(Image src_pix, int left, int top, int width, int height, std::vector< int > &thresholds, std::vector< int > &hi_values)
bool GetBoolVariable(const char *name, bool *value) const
bool GetDoubleVariable(const char *name, double *value) const
virtual Image GetPixRectThresholds()
int pix_wpl_
Words per line of pix_.
virtual void GetImageSizes(int *left, int *top, int *width, int *height, int *imagewidth, int *imageheight)
bool IsFullImage() const
Return true if we are processing the full image.
bool IsEmpty() const
Return true if no image has been set.
void SetImage(const unsigned char *imagedata, int width, int height, int bytes_per_pixel, int bytes_per_line)
int estimated_res_
Resolution estimate from text size.
virtual std::tuple< bool, Image, Image, Image > Threshold(TessBaseAPI *api, ThresholdMethod method)
virtual ~ImageThresholder()
void SetRectangle(int left, int top, int width, int height)
virtual void Init()
Common initialization shared between SetImage methods.
void OtsuThresholdRectToPix(Image src_pix, Image *out_pix) const
int scale_
Scale factor from original image.
int pix_channels_
Number of 8-bit channels in pix_.
int yres_
y pixels/inch in source image.
int image_width_
Width of source pix_.
virtual Image GetPixRectGrey()
void ThresholdRectToPix(Image src_pix, int num_channels, const std::vector< int > &thresholds, const std::vector< int > &hi_values, Image *pix) const
virtual bool ThresholdToPix(Image *pix)
Returns false on error.
bool IsBinary() const
Returns true if the source image is binary.
int image_height_
Height of source pix_.
virtual void Clear()
Destroy the Pix if there is one, freeing memory.