Delphi图像处理 -- 最大值

阅读提示:

    《Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。

    《C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。

    尽可能保持二者内容一致,可相互对照。

    本文代码必须包括文章《Delphi图像处理 -- 数据类型及公用过程》中的ImageData.pas单元

 

    图像的最大值处理就是以当前像素为中心,取周边一定半径范围内的所有像素的RGB分量的最大值,作为当前像素的分量值。如果图像含Alpha信息,则应对Alpha分量作一个相反的处理,即最小值处理。

procedure DoMaxValue(var Dest: TImageData; const Source: TImageData; Radius: Integer);
var
  height, iOffset, jOffset, dstOffset, srcOffset: Integer;
asm
    push      esi
    push      edi
    push      ebx
    push      ecx
    shl       ecx, 1
    mov       ebx, [edx].TImageData.Stride
    imul      ebx, ecx
    shl       ecx, 2
    add       ebx, ecx
    sub       ebx, 4
    neg       ebx
    mov       iOffset, ebx
    mov       ebx, [edx].TImageData.Stride
    push      ebx
    shl       ebx, 1
    sub       ebx, ecx
    mov       jOffset, ebx
    call      _SetCopyRegs
    mov       dstOffset, ebx
    mov       srcOffset, eax
    mov       height, edx
    pop       ebx
    pop       eax
@@yLoop:
    push      ecx
@@xLoop:
    mov       edx, eax
    pxor      mm0, mm0
    pxor      mm1, mm1
@@iLoop:
    push      eax
@@jLoop:
    pmaxub    mm1, [esi]
    pmaxub    mm1, [esi+ebx]
    add       esi, 8
    dec       eax
    jnz       @@jLoop
    pmaxub    mm0, [esi]
    pmaxub    mm0, [esi+ebx]
    pop       eax
    add       esi, jOffset
    dec       edx
    jnz       @@iLoop
    push      eax
@@jlLoop:
    pmaxub    mm1, [esi]
    add       esi, 8
    dec       eax
    jnz       @@jlLoop
    pop       eax
    pmaxub    mm0, [esi]
    pmaxub    mm0, mm1
    psrlq     mm1, 32
    pmaxub    mm0, mm1
    movd      [edi], mm0
    add       esi, iOffset
    add       edi, 4
    loop      @@xLoop
    pop       ecx
    add       esi, srcOffset
    add       edi, dstOffset
    dec       height
    jnz       @@yLoop
    pop       ebx
    pop       edi
    pop       esi
    emms
end;

procedure DoMinAlpha(var Dest: TImageData; const Source: TImageData; Radius: Integer);
var
  height, iOffset, jOffset, dstOffset, srcOffset: Integer;
asm
    push      esi
    push      edi
    push      ebx
    shl       ecx, 1
    inc       ecx
    push      ecx
    mov       ebx, [edx].TImageData.Stride
    imul      ebx, ecx
    sub       ebx, 4
    neg       ebx
    mov       iOffset, ebx
    shl       ecx, 2
    mov       ebx, [edx].TImageData.Stride
    sub       ebx, ecx
    mov       jOffset, ebx
    call      _SetCopyRegs
    mov       dstOffset, ebx
    mov       srcOffset, eax
    mov       height, edx
    add       esi, 3
    add       edi, 3
    pop       edx
@@yLoop:
    push      ecx
@@xLoop:
    mov       ebx, edx
    mov       eax, 255
@@iLoop:
    push      edx
@@jLoop:
    cmp       al, [esi]
    jbe       @@1
    mov       al, [esi]
@@1:
    add       esi, 4
    dec       edx
    jnz       @@jLoop
    pop       edx
    add       esi, jOffset
    dec       ebx
    jnz       @@iLoop
    mov       [edi], al
    add       esi, iOffset
    add       edi, 4
    loop      @@xLoop
    pop       ecx
    add       esi, srcOffset
    add       edi, dstOffset
    dec       height
    jnz       @@yLoop
    pop       ebx
    pop       edi
    pop       esi
end;

// 图像数据最大值处理。参数:图像数据,半径
procedure ImageMaxValue(var Data: TImageData; Radius: Integer);
var
  src: TImageData;
begin
  if Data.AlphaFlag then
    ArgbConvertPArgb(Data);           // 如果图像数据含Alpha信息,转换为PARGB
  src := _GetExpandData(Data, Radius);// 获取扩展半径后的图像数据源
  DoMaxValue(Data, src, Radius);      // 图像数据的最大值处理
  if Data.AlphaFlag then              // 如果图像数据含Alpha信息
  begin
    DoMinAlpha(Data, src, Radius);    // Alpha分量作最小值处理
    PArgbConvertArgb(Data);           // 还原PARGB为ARGB
  end;
  FreeImageData(src);
end;

 

    调用例子及运行效果:

procedure TForm1.Button3Click(Sender: TObject);
var
  bmp: TGpBitmap;
  g: TGpGraphics;
  data: TImageData;
begin
//  bmp := TGpBitmap.Create('..\..\media\apple.png');
  bmp := TGpBitmap.Create('..\..\media\source.bmp');
  data := LockGpBitmap(bmp);
  ImageMaxValue(data, 3);
  UnlockGpBitmap(bmp, data);
  g := TGpGraphics.Create(Canvas.Handle);
  g.DrawImage(bmp, 140, 0);
  g.Free;
  bmp.Free;
end;



  

    《Delphi图像处理》系列使用GDI+单元下载地址和说明见文章《GDI+ for VCL基础 -- GDI+ 与 VCL》。

    因水平有限,错误在所难免,欢迎指正和指导。邮箱地址:maozefa@hotmail.com

    这里可访问《Delphi图像处理 -- 文章索引》。

 

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Delphi11 是最新的 Delphi 版本,而 `delphi-opencv-master` 是一个开源的 Delphi 与 OpenCV 集成的项目,它提供了一组 Delphi 封装的 OpenCV 函数和类,方便 Delphi 开发者使用 OpenCV 进行图像处理和计算机视觉操作。 在 Delphi11 中,你可以通过以下步骤来使用 `delphi-opencv-master`: 1. 首先,你需要下载 `delphi-opencv-master` 项目的源代码,可以从 GitHub 上下载:https://github.com/Laex/Delphi-OpenCV 2. 解压缩下载的源代码,并将其中的 `OpenCV` 文件夹复制到 Delphi11 项目的根目录下。 3. 在 Delphi11 中打开你的项目,然后在菜单栏中选择 `Project` -> `Options` -> `Delphi Compiler` -> `Search Path`,将 OpenCV 文件夹所在的路径添加到搜索路径中。 4. 在 Delphi11 中使用 `uses` 语句引入 `OpenCV_Image` 单元,并调用其中的函数和类来进行图像处理和计算机视觉操作。 例如,以下代码演示了如何使用 `delphi-opencv-master` 进行图像读取和灰度化: ``` uses OpenCV_Image; var img: IplImage; begin // 读取图像 img := LoadImage('lena.jpg'); // 将图像转换为灰度图像 cvCvtColor(img, img, CV_RGB2GRAY); // 显示图像 ShowImage('My Image', img); // 等待用户按下任意键 WaitKey; // 释放图像内存 img.Release; end; ``` 这段代码使用了 `OpenCV_Image` 单元中提供的 `LoadImage` 函数和 `ShowImage` 函数来读取和显示图像,使用了 OpenCV 库中的 `cvCvtColor` 函数将图像转换为灰度图像。你可以根据自己的需要,使用 `delphi-opencv-master` 中提供的其他函数和类来进行更加复杂的图像处理和计算机视觉操作。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值