Digital image processing algorithm implementation ------------ Programming experience (1)

xiaoxiao2021-03-06  43

Digital image processing algorithm implementation

------------ Programming experience (1)

2001414 Class Zhu Wei 20014123

Summary: About spatial domain image processing algorithm framework, histogram processing, spatial field filter algorithm framework programming experience, using GDI (C )

First, the reading of the image file

When you begin a digital image processing, the reading of the image file is often a trouble, we have to face a variety of image file formats, if only C FSTREAM library, you must understand a variety of image encoding formats, this For beginner image processing, it is not realistic, requiring a library that can help easily read various image files. GDI (C ) on the Win32 platform is a good choice, not in use with respect to Win32 GDI more easily, and it is easy to transplant to GDI on the .NET platform.

GDIPLUS :: Bitmap class provides us with interfaces that read all kinds of image files, Bitmapdata class generated by the Bitmap :: Lockbits method also provides us with high-speed access to the image file stream. This allows us to focus on the implementation of the image processing algorithm without care for various image encodings. For details, please refer to the instructions for the Bitmap class and BitmapData classes in the GDI document in MSDN. In addition, GDI is only supported on Windows XP / 2003, and the related DLL must be installed for Windows 2000, or install software 2003, Visual Studio 2003 .NET and other software.

Second, spatial domain image processing algorithm framework

(1) In spatial domain image processing, for an image, we tend to process it one by one pixel, using the same algorithm for each pixel (or a rectangular portion in the image). That is, for the image f (x, y), where 0 ≤ x ≤ m, 0≤y ≤ N, the image is M * n size, using algorithm Algo, f (x, y) = algo (f (x, y) ))). A algorithm framework is implemented in advance, and then in the function pointer or function object (Functor, the OPERATOR () object) is incorporated into the algorithm, and the programming is reduced.

The following code is an example:

#ifndef processalgo_h

#define processalgo_h

#include

#include

Namespace NSIMGTK

{

Template

Bool ProcessPixelsonebyone (gdiplus :: bitmap * const p_bitmap, processor processor, unsigned int x, unsigned int y,

Unsigned int width, unsigned int hotht

{

IF (p_bitmap == null)

{

Return False;

}

IF ((width x> p_bitmap-> getWidth ()) || (Height Y> p_bitmap-> getHeight ())))

{

Return False;

}

GDIPLUS :: Bitmapdata Bitmapdata;

GDIPLUS :: Rect Re (X, Y, Width, Height);

IF (p_bitmap-> lockbits (& review, gdiplus :: imagelockmodewrite, pixelformmat, & bitmapdata)! = gdiplus :: ok) {

Return False;

}

PixelType * pixels = (pixeltype *) Bitmapdata.scan0;

For (unsigned int rot = 0); ROW

{

For (unsigned int coL = 0; col

{

Processor (& Pixels [Col Row * Bitmapdata.stride / sizeof (PixelType)]);

}

}

IF (p_bitmap-> unlockbits (& bitmapdata)! = gdiplus :: ok)

{

Return False;

}

Return True;

}

}

#ENDIF

The ProcessPixelsoneByone function can be processed from the (x, y) position from the (X, Y) position, and the Width * HEIGHT size is processed. The template parameter PixelType is used to specify the pixel size, for example, in the Win32 platform, which is incorporated into 8 bits, for 8-order gray graph. Template parameter processor is implemented for image processing algorithm, which can define a class implementation Void Operator (PixelTyPe *) function, or enters the function pointer to the same interface.

The following is some algorithm example (explained specific notes):

#ifndef spatialdomain_h

#define spatialdomain_h

#include

#include

Namespace NSIMGTK

{

// 8-order gray scale grayscale reversal algorithm

Class NegativeGRAY8

{

PUBLIC:

Void Operator () (unsigned char * const p_value)

{

* p_value ^ = 0xff;

}

}

// 8-order gray scale gamma correction algorithm

Class GammacorRectgray8

{

Private:

Unsigned char d_s [256];

PUBLIC:

GammacorRectGray8 :: GammacorRectgray8 (Double C, Double Gamma);

Void Operator () (unsigned char * const p_value)

{

* p_value = d_s [* p_value];

}

}

// 8-step gray graph saturation degree drawing algorithm

Class ContrastStretchinggray8

{

Private:

Unsigned char d_s [256];

PUBLIC:

Contraststretchinggray8 :: ContrastStretchinggray8 (Double A1, Double B1, Unsigned Int X1,

Double A2, Double B2, UNSIGNED INT X2, DOUBLE A3, DOUBLE B3);

Void Operator () (unsigned char * const p_value)

{

* p_value = d_s [* p_value];

}

}

// 8-order gray graph bit flat segmentation, constructor finger a positioning plane number

Class BitPlanesLicegray8

{

Private:

Unsigned char d_s [256];

PUBLIC:

BitPlanesLiceGray8 (unsigned char bitplanum);

Void Operator () (unsigned char * const p_value) {

* p_value = d_s [* p_value];

}

}

}

#ENDIF

/ / The implementation code of each constructor in the above class should be divided into another file, here is convenient, one and list

#include "spatialdomain / spatialdomain.h"

Namespace NSIMGTK

{

GammacorRectgray8 :: GammacorRectgray8 (Double C, Double Gamma)

{

Double Temp;

For (unsigned int = 0; i <256; i)

{

Temp = CEIL (C * 255.0 * Pow (Double (I) / 255.0, Gamma);

D_S [i] = unsigned char (TEMP);

}

}

Contraststretchinggray8 :: ContrastStretchinggray8 (Double A1, Double B1, Unsigned Int X1,

Double A2, Double B2, Unsigned Int X2, Double A3, Double B3)

{

IF (x1> 255 || x2> 255 || x1> x1)

{

For (unsigned int = 0; i <256; i)

D_S [i] = i;

}

Else

{

Double TMP;

For (unsigned int = 0; i

{

TMP = CEIL (A1 * DOUBLE (I) B1);

D_S [i] = (unsigned char) TMP;

}

For (unsigned int i = x1; i

{

TMP = CEIL (A2 * Double (i) b2);

D_S [i] = (unsigned char) TMP;

}

For (unsigned int = x2; i <256; i)

{

TMP = CEIL (A3 * DOUBLE (I) B3);

D_S [i] = (unsigned char) TMP;

}

}

}

BitPlanesLiceGray8 :: BitPlaneSlicegray8 (unsigned char bitplanum)

{

Unsigned char bitmaskArray [8] =

{

0x01, 0x02, 0x04, 0x08,

0x10, 0x20, 0x40, 0x80

}

For (unsigned int = 0; i <256; i)

{

UNSIGNED CHAR TMP = I;

TMP & = BitmaskArray [BitPlanenum];

TMP = (TMP >> BitPlanenum) * 255;

D_S [i] = TMP;

}

}

}

(2) The histogram is not supported in GDI 1.0, and we must implement itself. Template-related processing plays an important role in digital image processing, which can obtain statistics on image grayscale levels, and can perform some important image enhancements through histograms, such as histogram equalization, histogram regulations, Basic global threshold, etc.

Below is an algorithm for obtaining an 8-order image histogram:

Namespace NSIMGTK

{

Bool gethistogramnormalizegray8 (gdiplus :: bitmap * const p_bitmap, float * histogram axness) {

IF (p_bitmap == null || HistogramArray == NULL)

{

Return False;

}

GDIPLUS :: Bitmapdata Bitmapdata;

GDIPLUS :: Rect Rect (0, 0, p_bitmap-> getWidth (), p_bitmap-> getHeight ());

IF (P_bitmap-> Lockbits (& Rect, Gdiplus :: ImageLockModeRead, Pixelformata)! = gdiplus :: ok)

{

Return False;

}

Unsigned char * pixels = (unsigned char *) bitmapdata.scan0;

Unsigned int histogram [256];

For (int i = 0; i <256; i)

{

Histogram [i] = 0;

}

For (unsigned int = 0; row getWidth (); row)

{

For (unsigned int col = 0; col getHeight (); col)

{

Histogram [Pixels [Col Row * BitmapData.stride]];

}

}

Const unsigned int totalpixels = p_bitmap-> getWidth () * p_bitmap-> getHeight ();

For (int i = 0; i <256; i)

{

HistogramArray [I] = float (histogram [i]) / float (totalpixels);

}

IF (p_bitmap-> unlockbits (& bitmapdata)! = gdiplus :: ok)

{

Return False;

}

Return True;

}

}

After obtaining the histogram (ie the second parameter of the above algorithm), it is then incorporated into the constructor of the object as the parameter, and then incorporates the PROCESSPIELSONEBYONE in which the object is used as the implant function. :

#ifndef spatialdomain_h

#define spatialdomain_h

#include

#include

Namespace NSIMGTK

{

// 8-step graphic map equalization

Class HistogramequalizationGRAY8

{

Private:

Unsigned char d_s [256];

PUBLIC:

HistogramqualizationGRAY8 (Const Float * Const HistogramArray);

Void Operator () (unsigned char * const p_value)

{

* p_value = d_s [* p_value];

}

}

}

#ENDIF

//

#include "spatialdomain / spatialdomain.h"

Namespace NSIMGTK

{

HistogramequalizationGray8 :: HistogramEqualizationGray8 (Const Float * const histogram ax "{

IF (HistogramArray! = NULL)

{

FLOAT SUM = 0.0;

For (int i = 0; i <256; i)

{

SUM = HistogramArray [i];

D_S [i] = unsigned char (sum * 255);

}

}

}

}

(3) Spatial field filter, filter is a mask of a M * N size, where M, N is a odd number greater than 1. The filter is pixel through the entire or part of the rectangular area of ​​the image, and then the pixel of the mask is obtained by the pixel to the mask override, and the response is assigned to the current pixel, the center pixel, and the other filter algorithm is used. The problem of image edges will be involved, which can use the replacement of the edge portion mask to replace the unpixed value of the mask, or the moving range of the mask is moved in a manner that does not override the image edge, of course these processing The method will bring adverse effects to the image edge part, but in general, the image edge portion is often not part of our concern or there is no important information.

The following filter algorithm frame spatialfilteralgo is implemented by a zero-padding:

#ifndef spatialfilter_h

#define spatialfilter_h

#include

#include

#include

#include

#include

#include

Namespace NSIMGTK

{

Template

Bool Spatialfilteralgo (GDIPLUS :: Bitmap * const p_bitmap, filtermask filtermask, unsigned int x, unsigned int y,

Unsigned int width, unsigned int hotht

{

IF (p_bitmap == null)

{

Return False;

}

IF ((width x> p_bitmap-> getWidth ()) || (Height Y> p_bitmap-> getHeight ())))

{

Return False;

}

GDIPLUS :: Bitmapdata Bitmapdata;

GDIPLUS :: Rect Re (X, Y, Width, Height);

IF (P_bitmap-> Lockbits (& Rect, gdiplus :: imagelockmodewrite, pixelformat, & bitmapdata)! = gdiplus :: ok)

{

Return False;

}

PixelType * pixels = (pixeltype *) Bitmapdata.scan0;

Const unsigned int m = filtermask.d_m; // mask's width

Const unsigned int n = filtermask.d_n; // mask's heightstd :: Vector TmpImage ((M-1 Width) * (N-1 Height)); // Extend Image To Use Zero-Padding

// Copy Original Bitmap to Extended Image With Zero-PaddingMeet

For (unsigned int rot = 0); ROW

{

For (unsigned int coL = 0; col

{

TmpImage [(COL M / 2) (ROW N / 2) * (BitmapData.Stride / Sizeof (PixelType) M-1)] =

Pixels [col row * bitmapdata.stride / sizeof (PixelType)];

}

}

// Process Every Pixel with Filtermask

For (unsigned int rot = 0); ROW

{

For (unsigned int coL = 0; col

{

// Fill the "m * n" Mask with the capital Pixel's neighborhood

For (unsigned int = 0; i

{

For (unsigned int j = 0; j

{

Filtermask.d_mask [i * m j] = TmpImage [(COL J) (BitmapData.stride / sizeof (PixelType) M-1)];

}

}

// Replace The Current Pixel with Filter Mask's Response

Pixels [col row * bitmapdata.stride / sizeof (PixelType)] = filtermask.response ();

}

}

IF (p_bitmap-> unlockbits (& bitmapdata)! = gdiplus :: ok)

{

Return False;

}

Return True;

}

}

#ENDIF

The template parameter filtermask is a filter mask algorithm. The usual filter algorithm has a mean filter, which can be blurred, remove the detail portion in the graphic, so that we can focus on more obvious portions in the image, and the ape value filter is used for periodic noise. Medium-value filters are used in the case where the presence of pre-pepper noise is also pulse noise. In addition, there is a first-order differential Sobel gradient operator and a two-order differential Laplas operator, which is often used in edge detection.

Below is a specific implementation of some filter algorithms, so the filter algorithm should implement the PixelType Response () function and a member of D_Mask, D_M, D_N, which can be obtained by inheriting the __filtemask class (does not need to pay virtual functions).

#ifndef spatialfilter_h

#define spatialfilter_h

#include

#include

#include #include

#include

#include

Namespace NSIMGTK

{

// The base class of the filter mask provides a mask size D_M, D_N, M * n pixel value D_Mask under the mask cover.

// Others Filtermask Should Inherit IT

Template

Struct __filtermask

{

Const unsigned int d_m;

Const unsigned int d_n;

// Image's Pixels Under the M * N Filter Mask

Std :: Vector D_Mask;

// filter Mask's Width and Heigh Must Be A ODD, IF NOT, IT WILL PLUS One for the width or the height

__filtermask (unsigned Int M, unsigned int N)

: D_m (M% 2? M 1), D_N (N% 2? N: N 1), D_Mask (D_M * D_N)

{

}

}

// The mask power is all one value filter

Template

Class averagefiltermasksp

: public __filtermask

{

PUBLIC:

AveraGingFiltermasksp (unsigned int m, unsigned int N)

: __filtermask (M, N)

{}

PixelType Response ()

{

Return std :: accumulate (d_mask.begin (), d_mask.end (), 0) / (d_m * d_n);

}

}

/ / Customize a mean filter of the mask power value

Template

Class averagefiltermask

: public __filtermask

{

Private:

Std :: Vector D_Weight; // Weights' Vector (m * n)

INT D_WEIGHT_SUM; / / ALL Weights' SUM

PUBLIC:

AveraGingFiltermask (unsigned int m, unsigned int n, const st :: vector & weight)

: __filtermask (M, N), D_Weight (WeightVec)

{

IF (WeightVec.Size ()! = D_Mask.size ())

{

// if weight's size isn't equal to mask's size, IT Will Change Filter Mask As a Special Filter Mask

D_weight.resize (d_mask.size (), 1);

}

D_Weight_Sum = std :: accumulate (d_weight.begin (), d_weight.end (), 0);

}

PixelType Response () {

Return std :: inner_product (d_mask.begin (), d_mask.end (), d_weight.begin (), 0) / d_weight_sum;

}

}

// Medium value filter

Template

Class Medianfiltermask

: public __filtermask

{

PUBLIC:

MedianFiltermask (unsigned int M, unsigned int N)

: __filtermask (M, N)

{}

PixelType Response ()

{

Std :: sort (D_Mask.begin (), D_Mask.end ());

RETURN D_MASK [D_Mask.size () / 2];

}

}

// 3 * 3 Laplas filter

// the mask is: [0 1 0 [0 -1 0

// 1 -5 1 OR-1 5 -1

// 0 1 0] 0 ​​-1 0]

// if Pixel's Brightness Is Less Than Min, Set It To MIN

// if Pixel's Brightness Is Larger Than max, set it to max

Template

Class Laplacianfilter

: public __filtermask

{

PUBLIC:

LAPLACILTER ()

: __filtermask (3, 3)

{}

PixelType Response ()

{

INT RET = (int) (5 * (int) D_Mask [4]) - (INT) D_MASK [5] D_Mask [3] D_Mask [1] D_Mask [7]);

IF (RET

Ret = min;

IF (RET> MAX)

Ret = max;

Return Ret;

}

}

// 3 * 3Sobel filter

// the mask is: [-

1 -2 -1

[-1 0 1

// 0 0 0 and -2 0 2

// 1 2 1] -1 0 1]

// if Pixel's Brightness Is Larger Than max, set it to max

Template

Class Sobelfilter

: public __filtermask

{

PUBLIC:

Sobelfilter ()

: __filtermask (3, 3)

{}

PixelType Response ()

{

int RET = :: ABS (D_Mask [6] 2 * D_Mask [7] D_Mask [8] -d_mask [0] -2 * d_mask [1] -d_mask [2])

:: ABS (D_Mask [2] 2 * D_Mask [5] D_Mask [8] -d_mask [0] -2 * d_mask [3] -d_mask [6]);

IF (RET> MAX)

RET = max; return ret;

}

}

}

#ENDIF

Digital image processing algorithm implementation

------------ Programming experience (1)

2001414 Class Zhu Wei 20014123

Summary: About spatial domain image processing algorithm framework, histogram processing, spatial field filter algorithm framework programming experience, using GDI (C )

First, the reading of the image file

When you begin a digital image processing, the reading of the image file is often a trouble, we have to face a variety of image file formats, if only C FSTREAM library, you must understand a variety of image encoding formats, this For beginner image processing, it is not realistic, requiring a library that can help easily read various image files. GDI (C ) on the Win32 platform is a good choice, not in use with respect to Win32 GDI more easily, and it is easy to transplant to GDI on the .NET platform.

GDIPLUS :: Bitmap class provides us with interfaces that read all kinds of image files, Bitmapdata class generated by the Bitmap :: Lockbits method also provides us with high-speed access to the image file stream. This allows us to focus on the implementation of the image processing algorithm without care for various image encodings. For details, please refer to the instructions for the Bitmap class and BitmapData classes in the GDI document in MSDN. In addition, GDI is only supported on Windows XP / 2003, and the related DLL must be installed for Windows 2000, or install software 2003, Visual Studio 2003 .NET and other software.

Second, spatial domain image processing algorithm framework

(1) In spatial domain image processing, for an image, we tend to process it one by one pixel, using the same algorithm for each pixel (or a rectangular portion in the image). That is, for the image f (x, y), where 0 ≤ x ≤ m, 0≤y ≤ N, the image is M * n size, using algorithm Algo, f (x, y) = algo (f (x, y) ))). A algorithm framework is implemented in advance, and then in the function pointer or function object (Functor, the OPERATOR () object) is incorporated into the algorithm, and the programming is reduced.

The following code is an example:

#ifndef processalgo_h

#define processalgo_h

#include

#include

Namespace NSIMGTK

{

Template

Bool ProcessPixelsonebyone (gdiplus :: bitmap * const p_bitmap, processor processor, unsigned int x, unsigned int y,

Unsigned int width, unsigned int hotht

{

IF (p_bitmap == null)

{

Return False;

}

IF ((width x> p_bitmap-> getWidth ()) || (Height Y> p_bitmap-> getHeight ())))

{

Return False;

}

GDIPLUS :: Bitmapdata Bitmapdata;

GDIPLUS :: Rect Re (X, Y, Width, Height);

IF (p_bitmap-> lockbits (& review, gdiplus :: imagelockmodewrite, pixelformmat, & bitmapdata)! = gdiplus :: ok) {

Return False;

}

PixelType * pixels = (pixeltype *) Bitmapdata.scan0;

For (unsigned int rot = 0); ROW

{

For (unsigned int coL = 0; col

{

Processor (& Pixels [Col Row * Bitmapdata.stride / sizeof (PixelType)]);

}

}

IF (p_bitmap-> unlockbits (& bitmapdata)! = gdiplus :: ok)

{

Return False;

}

Return True;

}

}

#ENDIF

The ProcessPixelsoneByone function can be processed from the (x, y) position from the (X, Y) position, and the Width * HEIGHT size is processed. The template parameter PixelType is used to specify the pixel size, for example, in the Win32 platform, which is incorporated into 8 bits, for 8-order gray graph. Template parameter processor is implemented for image processing algorithm, which can define a class implementation Void Operator (PixelTyPe *) function, or enters the function pointer to the same interface.

The following is some algorithm example (explained specific notes):

#ifndef spatialdomain_h

#define spatialdomain_h

#include

#include

Namespace NSIMGTK

{

// 8-order gray scale grayscale reversal algorithm

Class NegativeGRAY8

{

PUBLIC:

Void Operator () (unsigned char * const p_value)

{

* p_value ^ = 0xff;

}

}

// 8-order gray scale gamma correction algorithm

Class GammacorRectgray8

{

Private:

Unsigned char d_s [256];

PUBLIC:

GammacorRectGray8 :: GammacorRectgray8 (Double C, Double Gamma);

Void Operator () (unsigned char * const p_value)

{

* p_value = d_s [* p_value];

}

}

// 8-step gray graph saturation degree drawing algorithm

Class ContrastStretchinggray8

{

Private:

Unsigned char d_s [256];

PUBLIC:

Contraststretchinggray8 :: ContrastStretchinggray8 (Double A1, Double B1, Unsigned Int X1,

Double A2, Double B2, UNSIGNED INT X2, DOUBLE A3, DOUBLE B3);

Void Operator () (unsigned char * const p_value)

{

* p_value = d_s [* p_value];

}

}

// 8-order gray graph bit flat segmentation, constructor finger a positioning plane number

Class BitPlanesLicegray8

{

Private:

Unsigned char d_s [256];

PUBLIC:

BitPlanesLiceGray8 (unsigned char bitplanum);

Void Operator () (unsigned char * const p_value) {

* p_value = d_s [* p_value];

}

}

}

#ENDIF

/ / The implementation code of each constructor in the above class should be divided into another file, here is convenient, one and list

#include "spatialdomain / spatialdomain.h"

Namespace NSIMGTK

{

GammacorRectgray8 :: GammacorRectgray8 (Double C, Double Gamma)

{

Double Temp;

For (unsigned int = 0; i <256; i)

{

Temp = CEIL (C * 255.0 * Pow (Double (I) / 255.0, Gamma);

D_S [i] = unsigned char (TEMP);

}

}

Contraststretchinggray8 :: ContrastStretchinggray8 (Double A1, Double B1, Unsigned Int X1,

Double A2, Double B2, Unsigned Int X2, Double A3, Double B3)

{

IF (x1> 255 || x2> 255 || x1> x1)

{

For (unsigned int = 0; i <256; i)

D_S [i] = i;

}

Else

{

Double TMP;

For (unsigned int = 0; i

{

TMP = CEIL (A1 * DOUBLE (I) B1);

D_S [i] = (unsigned char) TMP;

}

For (unsigned int i = x1; i

{

TMP = CEIL (A2 * Double (i) b2);

D_S [i] = (unsigned char) TMP;

}

For (unsigned int = x2; i <256; i)

{

TMP = CEIL (A3 * DOUBLE (I) B3);

D_S [i] = (unsigned char) TMP;

}

}

}

BitPlanesLiceGray8 :: BitPlaneSlicegray8 (unsigned char bitplanum)

{

Unsigned char bitmaskArray [8] =

{

0x01, 0x02, 0x04, 0x08,

0x10, 0x20, 0x40, 0x80

}

For (unsigned int = 0; i <256; i)

{

UNSIGNED CHAR TMP = I;

TMP & = BitmaskArray [BitPlanenum];

TMP = (TMP >> BitPlanenum) * 255;

D_S [i] = TMP;

}

}

}

(2) The histogram is not supported in GDI 1.0, and we must implement itself. Template-related processing plays an important role in digital image processing, which can obtain statistics on image grayscale levels, and can perform some important image enhancements through histograms, such as histogram equalization, histogram regulations, Basic global threshold, etc.

Below is an algorithm for obtaining an 8-order image histogram:

Namespace NSIMGTK

{

Bool gethistogramnormalizegray8 (gdiplus :: bitmap * const p_bitmap, float * histogram axness) {

IF (p_bitmap == null || HistogramArray == NULL)

{

Return False;

}

GDIPLUS :: Bitmapdata Bitmapdata;

GDIPLUS :: Rect Rect (0, 0, p_bitmap-> getWidth (), p_bitmap-> getHeight ());

IF (P_bitmap-> Lockbits (& Rect, Gdiplus :: ImageLockModeRead, Pixelformata)! = gdiplus :: ok)

{

Return False;

}

Unsigned char * pixels = (unsigned char *) bitmapdata.scan0;

Unsigned int histogram [256];

For (int i = 0; i <256; i)

{

Histogram [i] = 0;

}

For (unsigned int = 0; row getWidth (); row)

{

For (unsigned int col = 0; col getHeight (); col)

{

Histogram [Pixels [Col Row * BitmapData.stride]];

}

}

Const unsigned int totalpixels = p_bitmap-> getWidth () * p_bitmap-> getHeight ();

For (int i = 0; i <256; i)

{

HistogramArray [I] = float (histogram [i]) / float (totalpixels);

}

IF (p_bitmap-> unlockbits (& bitmapdata)! = gdiplus :: ok)

{

Return False;

}

Return True;

}

}

After obtaining the histogram (ie the second parameter of the above algorithm), it is then incorporated into the constructor of the object as the parameter, and then incorporates the PROCESSPIELSONEBYONE in which the object is used as the implant function. :

#ifndef spatialdomain_h

#define spatialdomain_h

#include

#include

Namespace NSIMGTK

{

// 8-step graphic map equalization

Class HistogramequalizationGRAY8

{

Private:

Unsigned char d_s [256];

PUBLIC:

HistogramqualizationGRAY8 (Const Float * Const HistogramArray);

Void Operator () (unsigned char * const p_value)

{

* p_value = d_s [* p_value];

}

}

}

#ENDIF

//

#include "spatialdomain / spatialdomain.h"

Namespace NSIMGTK

{

HistogramequalizationGray8 :: HistogramEqualizationGray8 (Const Float * const histogram ax "{

IF (HistogramArray! = NULL)

{

FLOAT SUM = 0.0;

For (int i = 0; i <256; i)

{

SUM = HistogramArray [i];

D_S [i] = unsigned char (sum * 255);

}

}

}

}

(3) Spatial field filter, filter is a mask of a M * N size, where M, N is a odd number greater than 1. The filter is pixel through the entire or part of the rectangular area of ​​the image, and then the pixel of the mask is obtained by the pixel to the mask override, and the response is assigned to the current pixel, the center pixel, and the other filter algorithm is used. The problem of image edges will be involved, which can use the replacement of the edge portion mask to replace the unpixed value of the mask, or the moving range of the mask is moved in a manner that does not override the image edge, of course these processing The method will bring adverse effects to the image edge part, but in general, the image edge portion is often not part of our concern or there is no important information.

The following filter algorithm frame spatialfilteralgo is implemented by a zero-padding:

#ifndef spatialfilter_h

#define spatialfilter_h

#include

#include

#include

#include

#include

#include

Namespace NSIMGTK

{

Template

Bool Spatialfilteralgo (GDIPLUS :: Bitmap * const p_bitmap, filtermask filtermask, unsigned int x, unsigned int y,

Unsigned int width, unsigned int hotht

{

IF (p_bitmap == null)

{

Return False;

}

IF ((width x> p_bitmap-> getWidth ()) || (Height Y> p_bitmap-> getHeight ())))

{

Return False;

}

GDIPLUS :: Bitmapdata Bitmapdata;

GDIPLUS :: Rect Re (X, Y, Width, Height);

IF (P_bitmap-> Lockbits (& Rect, gdiplus :: imagelockmodewrite, pixelformat, & bitmapdata)! = gdiplus :: ok)

{

Return False;

}

PixelType * pixels = (pixeltype *) Bitmapdata.scan0;

Const unsigned int m = filtermask.d_m; // mask's width

Const unsigned int n = filtermask.d_n; // mask's heightstd :: Vector TmpImage ((M-1 Width) * (N-1 Height)); // Extend Image To Use Zero-Padding

// Copy Original Bitmap to Extended Image With Zero-PaddingMeet

For (unsigned int rot = 0); ROW

{

For (unsigned int coL = 0; col

{

TmpImage [(COL M / 2) (ROW N / 2) * (BitmapData.Stride / Sizeof (PixelType) M-1)] =

Pixels [col row * bitmapdata.stride / sizeof (PixelType)];

}

}

// Process Every Pixel with Filtermask

For (unsigned int rot = 0); ROW

{

For (unsigned int coL = 0; col

{

// Fill the "m * n" Mask with the capital Pixel's neighborhood

For (unsigned int = 0; i

{

For (unsigned int j = 0; j

{

Filtermask.d_mask [i * m j] = TmpImage [(COL J) (BitmapData.stride / sizeof (PixelType) M-1)];

}

}

// Replace The Current Pixel with Filter Mask's Response

Pixels [col row * bitmapdata.stride / sizeof (PixelType)] = filtermask.response ();

}

}

IF (p_bitmap-> unlockbits (& bitmapdata)! = gdiplus :: ok)

{

Return False;

}

Return True;

}

}

#ENDIF

The template parameter filtermask is a filter mask algorithm. The usual filter algorithm has a mean filter, which can be blurred, remove the detail portion in the graphic, so that we can focus on more obvious portions in the image, and the ape value filter is used for periodic noise. Medium-value filters are used in the case where the presence of pre-pepper noise is also pulse noise. In addition, there is a first-order differential Sobel gradient operator and a two-order differential Laplas operator, which is often used in edge detection.

Below is a specific implementation of some filter algorithms, so the filter algorithm should implement the PixelType Response () function and a member of D_Mask, D_M, D_N, which can be obtained by inheriting the __filtemask class (does not need to pay virtual functions).

#ifndef spatialfilter_h

#define spatialfilter_h

#include

#include

#include #include

#include

#include

Namespace NSIMGTK

{

// The base class of the filter mask provides a mask size D_M, D_N, M * n pixel value D_Mask under the mask cover.

// Others Filtermask Should Inherit IT

Template

Struct __filtermask

{

Const unsigned int d_m;

Const unsigned int d_n;

// Image's Pixels Under the M * N Filter Mask

Std :: Vector D_Mask;

// filter Mask's Width and Heigh Must Be A ODD, IF NOT, IT WILL PLUS One for the width or the height

__filtermask (unsigned Int M, unsigned int N)

: D_m (M% 2? M 1), D_N (N% 2? N: N 1), D_Mask (D_M * D_N)

{

}

}

// The mask power is all one value filter

Template

Class averagefiltermasksp

: public __filtermask

{

PUBLIC:

AveraGingFiltermasksp (unsigned int m, unsigned int N)

: __filtermask (M, N)

{}

PixelType Response ()

{

Return std :: accumulate (d_mask.begin (), d_mask.end (), 0) / (d_m * d_n);

}

}

/ / Customize a mean filter of the mask power value

Template

Class averagefiltermask

: public __filtermask

{

Private:

Std :: Vector D_Weight; // Weights' Vector (m * n)

INT D_WEIGHT_SUM; / / ALL Weights' SUM

PUBLIC:

AveraGingFiltermask (unsigned int m, unsigned int n, const st :: vector & weight)

: __filtermask (M, N), D_Weight (WeightVec)

{

IF (WeightVec.Size ()! = D_Mask.size ())

{

// if weight's size isn't equal to mask's size, IT Will Change Filter Mask As a Special Filter Mask

D_weight.resize (d_mask.size (), 1);

}

D_Weight_Sum = std :: accumulate (d_weight.begin (), d_weight.end (), 0);

}

PixelType Response () {

Return std :: inner_product (d_mask.begin (), d_mask.end (), d_weight.begin (), 0) / d_weight_sum;

}

}

// Medium value filter

Template

Class Medianfiltermask

: public __filtermask

{

PUBLIC:

MedianFiltermask (unsigned int M, unsigned int N)

: __filtermask (M, N)

{}

PixelType Response ()

{

Std :: sort (D_Mask.begin (), D_Mask.end ());

RETURN D_MASK [D_Mask.size () / 2];

}

}

// 3 * 3 Laplas filter

// the mask is: [0 1 0 [0 -1 0

// 1 -5 1 OR-1 5 -1

// 0 1 0] 0 ​​-1 0]

// if Pixel's Brightness Is Less Than Min, Set It To MIN

// if Pixel's Brightness Is Larger Than max, set it to max

Template

Class Laplacianfilter

: public __filtermask

{

PUBLIC:

LAPLACILTER ()

: __filtermask (3, 3)

{}

PixelType Response ()

{

INT RET = (int) (5 * (int) D_Mask [4]) - (INT) D_MASK [5] D_Mask [3] D_Mask [1] D_Mask [7]);

IF (RET

Ret = min;

IF (RET> MAX)

Ret = max;

Return Ret;

}

}

// 3 * 3Sobel filter

// the mask is: [-

1 -2 -1

[-1 0 1

// 0 0 0 and -2 0 2

// 1 2 1] -1 0 1]

// if Pixel's Brightness Is Larger Than max, set it to max

Template

Class Sobelfilter

: public __filtermask

{

PUBLIC:

Sobelfilter ()

: __filtermask (3, 3)

{}

PixelType Response ()

{

int RET = :: ABS (D_Mask [6] 2 * D_Mask [7] D_Mask [8] -d_mask [0] -2 * d_mask [1] -d_mask [2])

:: ABS (D_Mask [2] 2 * D_Mask [5] D_Mask [8] -d_mask [0] -2 * d_mask [3] -d_mask [6]);

IF (RET> MAX)

RET = max; return ret;

}

}

}

#ENDIF

转载请注明原文地址:https://www.9cbs.com/read-76280.html

New Post(0)