Bernsen Thresholding gamera (8-) - (1-).
Bernsen Thresholding - (. ). .
Bernsen Thresholding. :
bernsen_thres <input_file> <region_size (int)> <contrast_limit (unsigned)> <set_doubt_to_low (bool)>
region_size - . 3 ( 8).
contrast_limit - . 128.
set_doubt_to_low - . 0.
, .
.
( , , - bat- ) :
bernsen_thres (36 )
( FreeImage dll- FreeImage DLL v3.9.2 - . 1. FreeImage).
:
/*
*
* Copyright (C) 2001-2005 Ichiro Fujinaga, Michael Droettboom, and Karl MacMillan
*
* 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 2
* of the License, or (at your option) 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
References:
&'John Bernsen'
"Dynamic thresholding of grey-level images",
Proc. 8th International Conference on Pattern
Recognition (ICPR8), pp 1251-1255, Paris, France,
October 1986.
Original author:
Øivind Due Trier
*/
/*
Creates a binary image by using the Bernsen algorithm.
*region_size* : default = 3
The size of each region in which to calculate a threshold
*contrast_limit* : default = 128
The minimum amount of contrast required to threshold.
*set_doubt_to_low* : default = 0
The color choice for the doubt pixels
*/
// This algorithm was taken from the gamera.sf.net sourcecodes
// and adopted for the FreeImage library
//
// Copyright (C) 2007-2008:
// monday2000 monday2000@yandex.ru
#include "FreeImage.h"
#include "Utilities.h"
////////////////////////////////////////////////////////////////////////////////
inline void SetPixel(BYTE *bits, unsigned x, BYTE* value)
{ // this function is simplified from FreeImage_SetPixelIndex
*value ? bits[x >> 3] |= (0x80 >> (x & 0x7)) : bits[x >> 3] &= (0xFF7F >> (x & 0x7));
}
////////////////////////////////////////////////////////////////////////////////
FIBITMAP* ProcessFilter(FIBITMAP* src_dib, int region_size, unsigned contrast_limit, BOOL set_doubt_to_low)
{
unsigned width = FreeImage_GetWidth(src_dib);
unsigned height = FreeImage_GetHeight(src_dib);
unsigned src_pitch = FreeImage_GetPitch(src_dib);
unsigned bpp = FreeImage_GetBPP(src_dib);
FIBITMAP* dst_dib = FreeImage_Allocate(width, height, 1);
// Build a monochrome palette
RGBQUAD *pal = FreeImage_GetPalette(dst_dib);
pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
unsigned dst_pitch = FreeImage_GetPitch(dst_dib);
BYTE* src_bits = (BYTE*)FreeImage_GetBits(src_dib); // The image raster
BYTE* dst_bits = (BYTE*)FreeImage_GetBits(dst_dib); // The image raster
unsigned x, y, i, j;
int k_index;
BYTE* src_end_row = src_bits + (height-1) * src_pitch;
int end_col = width - 1;
BYTE* lines, *linek, *lined;
BYTE confused, val, c;
BYTE minimum;
BYTE maximum;
if (set_doubt_to_low)
confused = 0; //black
else
confused = 255; // white
for (y = 0; y < height; y++)
{
lines = src_bits + y * src_pitch;
lined = dst_bits + y * dst_pitch;
for (x = 0; x < width; x++)
{
minimum = 255;
maximum = 0;
// kernel processing
for (i = 0; i < region_size; i++)
for (j = 0; j < region_size; j++)
{
linek = lines + (i-1) * src_pitch;
if (linek < src_bits) linek = src_bits;
if (linek > src_end_row) linek = src_end_row;
k_index = x+j-1;
if (k_index < 0) k_index = 0;
if (k_index > end_col) k_index = end_col;
minimum = MIN(minimum, linek[k_index]);
maximum = MAX(maximum, linek[k_index]);
}
c = maximum - minimum;
if (c < contrast_limit)
val = confused;
else
{
long t = (maximum + minimum) / 2;
if (lines[x] >= t)
val = 255; // white
else
val = 0; // black
}
SetPixel(lined, x, &val);
}
}
// Copying the DPI...
FreeImage_SetDotsPerMeterX(dst_dib, FreeImage_GetDotsPerMeterX(src_dib));
FreeImage_SetDotsPerMeterY(dst_dib, FreeImage_GetDotsPerMeterY(src_dib));
return dst_dib;
}
////////////////////////////////////////////////////////////////////////////////
/**
FreeImage error handler
@param fif Format / Plugin responsible for the error
@param message Error message
*/
void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
printf("\n*** ");
printf("%s Format\n", FreeImage_GetFormatFromFIF(fif));
printf(message);
printf(" ***\n");
}
////////////////////////////////////////////////////////////////////////////////
/** Generic image loader
@param lpszPathName Pointer to the full file name
@param flag Optional load flag constant
@return Returns the loaded dib if successful, returns NULL otherwise
*/
FIBITMAP* GenericLoader(const char* lpszPathName, int flag)
{
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
// check the file signature and deduce its format
// (the second argument is currently not used by FreeImage)
fif = FreeImage_GetFileType(lpszPathName, 0);
FIBITMAP* dib;
if(fif == FIF_UNKNOWN)
{
// no signature ?
// try to guess the file format from the file extension
fif = FreeImage_GetFIFFromFilename(lpszPathName);
}
// check that the plugin has reading capabilities ...
if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif))
{
// ok, let's load the file
dib = FreeImage_Load(fif, lpszPathName, flag);
// unless a bad file format, we are done !
if (!dib)
{
printf("%s%s%s\n","File \"", lpszPathName, "\" not found.");
return NULL;
}
}
return dib;
}
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]) {
// call this ONLY when linking with FreeImage as a static library
#ifdef FREEIMAGE_LIB
FreeImage_Initialise();
#endif // FREEIMAGE_LIB
// initialize your own FreeImage error handler
FreeImage_SetOutputMessage(FreeImageErrorHandler);
if(argc != 5) {
printf("Usage : bernsen_thres <input_file> <region_size (int)> <contrast_limit (unsigned)> <set_doubt_to_low (int)>\n");
return 0;
}
FIBITMAP *dib = GenericLoader(argv[1], 0);
int region_size = atoi(argv[2]);
unsigned contrast_limit = atoi(argv[3]);
int set_doubt_to_low = atoi(argv[4]);
if (dib)
{
// bitmap is successfully loaded!
if (FreeImage_GetImageType(dib) == FIT_BITMAP)
{
if (FreeImage_GetBPP(dib) == 8)
{
FIBITMAP* dst_dib = ProcessFilter(dib, region_size, contrast_limit, set_doubt_to_low);
if (dst_dib)
{
// save the filtered bitmap
const char *output_filename = "filtered.tif";
// first, check the output format from the file name or file extension
FREE_IMAGE_FORMAT out_fif = FreeImage_GetFIFFromFilename(output_filename);
if(out_fif != FIF_UNKNOWN)
{
// then save the file
FreeImage_Save(out_fif, dst_dib, output_filename, 0);
}
// free the loaded FIBITMAP
FreeImage_Unload(dst_dib);
}
}
else
printf("%s\n", "Unsupported color mode.");
}
else // non-FIT_BITMAP images are not supported.
printf("%s\n", "Unsupported color mode.");
FreeImage_Unload(dib);
}
// call this ONLY when linking with FreeImage as a static library
#ifdef FREEIMAGE_LIB
FreeImage_DeInitialise();
#endif // FREEIMAGE_LIB
return 0;
}
|
33 . . - , - . - , " ".
, , - , . = 6 - " ". = 1 - .