📄 unit1.~pas
字号:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls, ExtDlgs;
type
TForm1 = class(TForm)
Image1: TImage;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
OpenPictureDialog1: TOpenPictureDialog;
SavePictureDialog1: TSavePictureDialog;
Button1: TButton;
procedure BitBtn1Click(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure huidu(bmp:TBitmap);//转为灰度图
procedure GetParam(bmp:TBitmap);//动态阈值时要用的参数计算(取最大和最小灰度)
procedure erzhihua(fazhi:integer;bmp:TBitmap);//图象二值化
procedure lktq(b1:TBitmap);//轮廓提取
public
{ Public declarations }
end;
var
Form1: TForm1;
OriginalRangeLeft, OriginalRangeRight,fazhi: integer;
Grayclass: array[0..255] of integer;
implementation
{$R *.dfm}
procedure TForm1.lktq(b1:Tbitmap);
var
b0: Tbitmap;
i, j: Integer;
p1, p2, p3, p4: pbyteArray;
begin
b0 := Tbitmap.Create;
b0.Assign(b1);
b0.PixelFormat := pf24bit;
b1.PixelFormat := pf24bit;
for i := 1 to b0.Height - 2 do
begin
p1 := b0.ScanLine[i - 1];
p2 := b0.ScanLine[i];
p3 := b0.ScanLine[i + 1];
p4 := b1.ScanLine[i];
for j := 1 to b0.Width - 2 do
begin
if (p2[3 * j + 2] = 0) and (p2[3 * j + 1] = 0) and (p2[3 * j] = 0) then
begin
if ((p2[3 * (j - 1) + 2] = 0) and (p2[3 * (j - 1) + 1] = 0) and
(p2[3 * (j - 1)] = 0)) and
((p2[3 * (j + 1) + 2] = 0) and (p2[3 * (j + 1) + 1] = 0) and
(p2[3 * (j + 1)] = 0)) and
((p1[3 * (j + 1) + 2] = 0) and (p1[3 * (j + 1) + 1] = 0) and
(p1[3 * (j + 1)] = 0)) and
((p1[3 * (j) + 2] = 0) and (p1[3 * (j) + 1] = 0) and (p1[3 * (j)]
= 0)) and
((p1[3 * (j - 1) + 2] = 0) and (p1[3 * (j - 1) + 1] = 0) and
(p1[3 * (j - 1)] = 0)) and
((p3[3 * (j - 1) + 2] = 0) and (p3[3 * (j - 1) + 1] = 0) and
(p3[3 * (j - 1)] = 0)) and
((p3[3 * (j) + 2] = 0) and (p3[3 * (j) + 1] = 0) and (p3[3 * (j)]
= 0)) and
((p3[3 * (j + 1) + 2] = 0) and (p3[3 * (j + 1) + 1] = 0) and
(p3[3 * (j + 1)] = 0)) then
begin
p4[3 * j + 2] := 255;
p4[3 * j + 1] := 255;
p4[3 * j] := 255;
end;
end;
end;
end;
b0.Free;
end;
procedure TForm1.huidu(bmp:TBitmap);
var
p: pbyteArray;
x, y: Integer;
Gray: integer;
begin
Bmp.PixelFormat := pf24bit;
for y := 0 to Bmp.Height - 1 do
begin
//获取每一行象素信息
p := Bmp.scanline[y];
for x := 0 to Bmp.Width - 1 do
begin
//即 Y=0.299R+0587G+0.114B
Gray := Round(p[3 * x + 2] * 0.3 + p[3 * x + 1] * 0.59
+ p[3 * x] * 0.11);
//由于是24位真彩色,故一个象素点为三个字节
p[3 * x + 2] := byte(Gray);
p[3 * x + 1] := byte(Gray);
p[3 * x] := byte(Gray);
//Gray的值必须在0~255之间
end;
end;
end;
procedure TForm1.GetParam(bmp:Tbitmap);
var
p: PByteArray;
// PbyteArray类型
x, y, i, j: Integer;
Gray: byte;
scanlinebytes: integer;
//扫描线间距
begin
Bmp.PixelFormat := pf24Bit;
p := Bmp.scanline[0];
//首行扫描线信息
for i := 0 to 255 do
begin
Grayclass[i] := 0;
//初始化数组为0
end;
scanlinebytes := integer(Bmp.scanline[1]) - integer(Bmp.scanline[0]);
for y := 0 to Bmp.Height - 1 do
begin
//注意边界,不能越界
for x := 0 to Bmp.Width - 1 do
begin
Gray := round(p[x * 3 + 2] * 0.3 + p[x * 3 + 1] * 0.59 + p[x
* 3]
* 0.11);
//求取灰度值
for i := 0 to 255 do
begin
if Gray = i then
begin
Grayclass[i] := Grayclass[i] + 1;
//每级灰度象素点数
end;
end;
end;
inc(integer(p), scanlinebytes);
//指针增加,增加得其实是一个负值
end;
for i := 0 to 255 do
begin
if grayclass[i] <> 0 then
begin
OriginalRangeLeft := i;
break;
//获取最大灰度级
end;
end;
for j := 255 downto 0 do
begin
if grayclass[j] <> 0 then
begin
OriginalRangeRight := j;
break;
//获取最小灰度级
end;
end;
end;
procedure TForm1.erzhihua(fazhi:integer;bmp:TBitmap);
var
p: PByteArray;
Gray, x, y: Integer;
begin
Bmp.PixelFormat := pf24Bit;
//randomize;
for y := 0 to Bmp.Height - 1 do
begin
p := Bmp.scanline[y];
for x := 0 to Bmp.Width - 1 do
begin
//一个象素点三个字节
Gray := Round(p[x * 3 + 2] * 0.3 + p[x * 3 + 1] * 0.59 + p[x
* 3] * 0.11);
if gray > fazhi then //全局阀值
begin
p[x * 3] := 255;
p[x * 3 + 1] := 255;
p[x * 3 + 2] := 255;
end
else
begin
p[x * 3] := 0;
p[x * 3 + 1] := 0;
p[x * 3 + 2] := 0;
end;
end;
end;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
// if not image1.Picture.Bitmap.Empty then image1.Picture.Bitmap.CleanupInstance;
//Self.OpenPictureDialog1.Filter := '*.bmp|*.bmp';
if Self.OpenPictureDialog1.Execute then
begin
Image1.picture.Bitmap.LoadFromFile(Self.OpenPictureDialog1.FileName);
end;
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
var
bmpS:Tbitmap;
begin
bmps:=Tbitmap.Create;
bmps.Assign(Image1.picture.Bitmap);
bmps.Width:=Image1.picture.Bitmap.Width;
bmps.Height:=Image1.picture.Bitmap.Height;
Image1.Width:=Image1.picture.Bitmap.Width; //便于你观看结果,因为image太小时有的线条可能看不见
Image1.Height:=Image1.picture.Bitmap.Height;
huidu(bmps);
GetParam(bmpS);
fazhi:= round(OriginalRangeRight-(OriginalRangeRight-OriginalRangeLeft) div 3); //这个算法是怎么推论出来的我就不多说
//erzhihua(fazhi,bmpS);
//lktq(bmps);
image1.Picture.Bitmap.Assign(bmps);
bmps.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
//Self.SavePictureDialog1.Filter := '*.bmp|*.bmp';
if SavePictureDialog1.Execute then image1.Picture.SaveToFile(SavePictureDialog1.FileName+'.bmp');
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -