I have seen some books about image processing, which has played a lot of help to me. So, today I have sorted out the knowledge I have learned. On the one hand, I can give people to learn. On the other hand, you can also ask your guidance.
The image processing I want to say is for the program. So, make a program to place graphics. Here, I used Delphi as a tool. Because, in the many compilers I have, Delphi supports the graphics. Also, here I am not talking about the syntax. So some code I will not explain. Sorry for any inconveniences caused.
Note: The things used in this article are not exceeding the range of GDI.
In image processing, the speed is important. Therefore, we have to reprocess Tbitmap and get TVCZHbitmap. This is just because getpixels and setpixels are too slow, change a method.
UNIT UNTMAPPROC;
Interface
Uses graphics, sysutils;
Type
TVCzhbitmap = Class (Tbitmap)
Private
Data: PbyteArray;
Line: integer;
Procedure setFormat;
Function GetBytepointer (x, y: integer): pbyte;
Procedure setbytes (x, y: integer; value: byte);
Function Gettes (X, Y: Integer): byte;
protected
Published
Constructor crete;
public
Property Bytes [x, y: integer]: byte read getBytes Write SetBytes;
Procedure loadFromfile (filename: string);
PROCEDURE TOGRAY;
END;
IMPLEMentation
Procedure tvczhbitmap.setformat;
Begin
Handletype: = BMDIB;
Pixelformat: = PF24bit;
END;
Function TVCzhbitmap.getbytepointer (x, y: integer): pbyte;
Begin
IF line <> y tell
Begin
Line: = Y;
Data: = scanline [y];
END;
Longint (result): = longint (data) x;
END;
Procedure tvczhbitmap.setbytes (x, y: integer; value: byte);
Begin
GetBytepointer (x, y) ^: = value;
END;
Function tvczhbitmap.getbytes (x, y: integer): byte;
Begin
Result: = GetBytepointer (x, y) ^;
END;
Constructor tvczhbitmap.create;
Begin
Inherited Create;
SetFormat;
Line: = - 1;
END;
Procedure tvczhbitmap.LoadFromFile (filename: string);
Begin
Inherited loadFromfile (filename);
SetFormat;
Line: = - 1;
END;
Procedure tvczhbitmap.toGray;
VAR X, Y, R: Integer;
B: BYTE;
Begin
For Y: = 0 to Height-1 DO
For x: = 0 to width-1 do
Begin
R: = 0; for b: = 0 to 2 DO
R: = R GetBytes (x * 3 b, y);
For b: = 0 to 2 DO
SetBytes (x * 3 b, y, r div 3);
END;
END;
End.
Since then, we need to build several forms. The first is used to display pictures, and the second is used to process pictures, and other forms are inherited from the second form, including actual processing methods.
First look at the second window:
UNIT UNTPROC;
Interface
Uses
Windows, Messages, Sysutils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, UnTbitmApproc, Stdctrls, Comctrls;
Type
TFRMProcessor = Class (TFORM)
PBBAR: TPAINTBOX;
GPPROC: TGROUPBOX;
Button1: tbutton;
Procedure formcreate (Sender: TOBJECT);
Procedure FormDestroy (Sender: TOBJECT);
Procedure FormShow (Sender: TOBJECT);
Procedure PBBARPAINT (Sender: TOBJECT);
Procedure Button1Click (Sender: TOBJECT);
Private
{Private Declarations}
public
{Public declarations}
Bardata: array [0..255] of byte;
Bar: tvczhbitmap;
Procedure drawbar;
END;
VAR
FRMPROCESSOR: TFRMPROCESSOR;
IMPLEMentation
{$ R * .dfm}
Uses unpViewer;
Procedure tfrmprocessor.drawbar;
VAR i: integer;
Begin
Bar.canvas.fillRect (bar.canvas.cliprect);
Bar.canvas.moveto (0,255-Bardata [0]);
For i: = 1 to 255 do
Bar.canvas.LineTo (i, 255-barata [i]);
END;
Procedure tfrmprocessor.formcreate (sender: TOBJECT);
Begin
Bar: = tvczhbitmap.create;
Bar.width: = 256;
Bar.height: = 256;
Bar.canvas.brush.color: = CLWHITE;
Bar.canvas.brush.style :=bssolid;
END;
Procedure TfrmProcessor.formDestroy (Sender: TOBJECT);
Begin
Bar.free;
END;
Procedure tfrmprocessor.formshow (sender: TOBJECT);
VAR i: integer;
Begin
For i: = 0 to 255 do
Bardata [I]: = i;
Drawbar;
END;
Procedure tfrmprocessor.pbbarpaint (sender: TOBJECT);
Begin
Pbbar.canvas.draw (0, 0, bar);
END;
Procedure TfrmProcessor.Button1Click (Sender: TOBJECT);
VAR X, Y: Integer;
Begin
For Y: = 0 to buffer.Height-1 DOFOR x: = 0 to buffer.width * 3-1 DO
Played.Bytes [x, y]: = Bardata [buffer.bytes [x, y]];
FrmViewer.FormPaint (frmviewer);
END;
End.
After that, make a window inheritance from it, then adjust the BARDATA [], press Apply to see the result.
Image processing is now processed. See the sample program for the specific effect.
First, the color reverses.
The color of the grayscale image is from 0 to 255, so in order to reverse the color, we can use 255 to subtract the color value to get the inversion.
VAR i: integer;
Begin
inherited;
For i: = 0 to 255 do
Bardata [i]: = 255-i; // minus the color value with 255
Drawbar;
PBBARPAINT (PBBAR);
END;
Second, reduce the color range to enhance or reduce brightness
The color is originally from 0 to 255. If it is adjusted, for example from 0 to 16, it will be significantly dimmed. We can set the start value to a, set the termination value to B, then the new color value new = a (b-1) * OLD / 255. If this is done, the brightness can be changed and the order in which the original color is not destroyed. code show as below
VAR i: integer;
Begin
For i: = 0 to 255 do
Bardata [I]: = (255-sbmin.position) Round ((sbmin.position-sbmax.position) / 255 * i);
Drawbar;
PBBARPAINT (PBBAR);
Button1click (Button1);
END;
The sbmin.position and sbmaxposition here are reversed. So use 255 to reduce
Third, add a range of color within a certain range
If the color range of the image itself is small, you can increase the contrast of the image in this way, which is conducive to the analysis of the image. specific methods:
Select a value a as the start value, select a value B as a termination value, then behave in the following formula:
| 0 (x <= a)
f (x) = | 255 / (b-a) * (x-a)
| 255 (x> = b)
VAR i: integer;
Begin
For i: = 0 to 255 do
Begin
IF i <= sbmin.position then
Bardata [I]: = 0
Else if i> = sbmax.position thein
Bardata [I]: = 255
Else
Bardata [I]: = ROUND (255 / (sbmax.position-sbmin.position) * (i-sbmin.position));
END;
Drawbar;
PBBARPAINT (PBBAR);
Button1click (Button1);
END;
Fourth, become a black and white picture
When using the third function, you will find that when B <= a, the color on the image is white in addition to the black. The advantage of this operation cannot be displayed directly. This is only possible to have a relatively advanced image processing such as edge detection. In this case, the formula of the third method can be reformable, so it is not described in detail.
V. Exponential brightness adjustment
We assume that the defined domain of this figure is [0, 1], and the value field is also [0, 1]. Then, the definition function f (x) = x ^ c, then the image of F (X) has a paragraph. When we use the mouse to operate, it can be taken to P (A, B) above, and then f (x) passes Point P, then C = ln (b) / ln (a). After I have C, we can operate the color: new = (old / 255) ^ c * 255 = exp (ln (old / 255) * c) * 255
Var EA, EB, EC: extended
I: integer;
Begin
EA: = a / 255;
EB: = B / 255;
EC: = ln (EB) / LN (EA);
For i: = 1 to 255 do
Bardata [I]: = ROUND (EXP (LN (((((((((I / 255)) * EC) * 255);
Drawbar;
PBBARPAINT (PBBAR);
Button1click (Button1);
END;
Doing so can adjust the brightness of the image.
First come here, in the next article, I will sort out the method of color image brightness adjustment.
Sample program: http://vczh.cstc.net.cn/vczh/article/a_files/gray256.rar Open, press Right-click Menu