一种简单的图像分析

简介

一种简单的边界分析,通过相邻的像素的灰度进行判断,计算出边界。

测试1

原图

结果

测试2

原图

结果

代码说明

主要的技术在makeTable过程中,这个过程主要执行了以下几步

  1. 计算每个像素的灰度
  2. 计算相邻多个像素的最大灰度差
  3. 统计灰度差,计算出阈值
  4. 根据阈值,计算出边界,并标注在图像上

procedure makeTable(img: TBitmap32);
var
  w, h, w_r, h_r, x, y, k, r_count, Pcount: Integer;
  bmp2, bmp: TBitmap32;
  blist: TByteTable;
  blist_diff: TByteTable;
  b, b1, b2, maxa: byte;
  c32: TColor32Entry;
  sum, stepCount, count: integer;
  idx, i, j, s_x_1, s_x_2: integer;
  s_y_1, s_y_2: integer;
  c_b: array[0..255] of integer;
  FilterB: Byte;
  Filter_Count: integer;
  Filter_Sum: integer;

  RectList: array of array of TRectRec;
  r: Trect;
  pt_1, path: array of TPoint;
  fillcount, maxfillcount: integer;
  function check_r(i, j: integer; pt: array of TPoint): Boolean;
  var
    idx: integer;
  begin
    Result := false;
    if RectList[i, j].count <= 0 then
      exit;

    for idx := 0 to high(pt) do
      begin
        if RectList[i + pt[idx].X, j + pt[idx].y].count > 0 then
          begin
            Result := false;
            Exit;
          end;
      end;
    Result := true;
  end;
  procedure getFill(x, y: integer; pt: array of TPoint; MaxCount: integer; var path: array of TPoint; var count: integer);
  var
    idx: integer;
    ax, ay: integer;
  begin
    if x < 0 then
      Exit;
    if y < 0 then
      Exit;
    if x >= w_r then
      Exit;
    if y >= h_r then
      Exit;
    if RectList[x, y].count <= 0 then
      Exit;
    if count >= MaxCount then
      exit;
    for idx := count - 1 downto 0 do
      begin
        if (path[idx].X = x) and (path[idx].y = y) then
          begin
            Exit;
          end;
      end;
    path[count] := Point(x, y);
    inc(count);
    if count >= MaxCount then
      exit;
    for idx := 0 to high(pt) do
      begin
        ax := x + pt[idx].X;
        ay := y + pt[idx].Y;
        getFill(ax, ay, pt, MaxCount, path, count);
      end;
  end;
begin
  w := img.Width;
  h := img.Height;

  SetLength(blist, w);
  for x := 0 to w - 1 do
    SetLength(blist[x], h);
  SetLength(blist_diff, w);
  for x := 0 to w - 1 do
    SetLength(blist_diff[x], h);

  for x := 0 to w - 1 do
    for y := 0 to h - 1 do
      begin
        c32.ARGB := img.Pixel[x, y];
        b := (77 * c32.R + 150 * c32.G + 29 * c32.B) shr 8;
        blist[x, y] := b;
      end;

  bmp2 := TBitmap32.Create;
  bmp2.SetSize(w, h);
  maxa := 0;
  stepCount := 5;
  for x := 0 to w - 1 do
    for y := 0 to h - 1 do
      begin
        count := min(x - 0 + 1, stepCount);
        s_x_1 := getsum(blist, x, y, -1, 0, count);
        count := min(w - x, stepCount);
        s_x_2 := getsum(blist, x, y, 1, 0, count);

        count := min(y - 0 + 1, stepCount);
        s_y_1 := getsum(blist, x, y, 0, -1, count);
        count := min(h - y, stepCount);
        s_y_2 := getsum(blist, x, y, 0, 1, count);

        b := max(abs(s_x_1 - s_x_2), abs(s_y_1 - s_y_2));
        blist_diff[x, y] := b;
        if b > maxa then
          maxa := b;
      end;

  ZeroMemory(@(c_b[0]), length(c_b) * sizeof(i));
  Pcount := 0;
  for x := 0 to w - 1 do
    for y := 0 to h - 1 do
      begin
        b := blist_diff[x, y];
        b := 255 * b div maxa;
        blist_diff[x, y] := b;
        inc(c_b[b]);
        inc(Pcount);
      end;
  FilterB := 0;
  count := 0;
  for i := 0 to 255 do
    begin
      inc(count, c_b[i]);
      if count > (Pcount div 2) then
        begin
          FilterB := i ;
          Break;
        end
    end;

  Pcount := 0;
  for x := 0 to w - 1 do
    for y := 0 to h - 1 do
      begin

        if blist_diff[x, y] < FilterB then
          blist_diff[x, y] := 0;
      end;
  x := 0;
  y := 0;
  r_count := 10;
  w_r := (w - 1) div r_count + 1;
  h_r := (h - 1) div r_count + 1;

  SetLength(RectList, w_r);
  for x := 0 to w_r - 1 do
    SetLength(RectList[x], h_r);

  for i := 0 to w_r - 1 do
    for j := 0 to h_r - 1 do
      begin
        x := (i) * r_count;
        y := (j) * r_count;
        r.Left := x;
        r.Top := y;
        r.Right := Min(x + r_count, w);
        r.Bottom := Min(y + r_count, h);
        RectList[i, j].rect := r;
        RectList[i, j].sum := 0;
        RectList[i, j].count := 0;
      end;
  count := 0;
  sum := 0;
  for x := 0 to w - 1 do
    for y := 0 to h - 1 do
      begin
        b := blist_diff[x, y];
        if b = 0 then
          Continue;
        i := x div (r_count);
        j := y div (r_count);
        inc(RectList[i, j].sum, b);
        inc(RectList[i, j].count);
        inc(sum, b);
        inc(count);
      end;

  Filter_Sum := sum div count;
  Filter_Count := max(r_count, count div (w_r * h_r));
  setlength(pt_1, 8);
  pt_1[0] := Point(-1, -1);
  pt_1[1] := Point(0, -1);
  pt_1[2] := Point(+1, -1);
  pt_1[3] := Point(-1, 0);
  pt_1[4] := Point(+1, 0);
  pt_1[5] := Point(-1, +1);
  pt_1[6] := Point(0, +1);
  pt_1[7] := Point(-1, +1);

  for i := 0 to w_r - 1 do
    for j := 0 to h_r - 1 do
      begin
        if RectList[i, j].count < Filter_Count then
          begin
            RectList[i, j].count := 0
          end
        else
          begin
            if RectList[i, j].sum < (Filter_Sum * RectList[i, j].count) then
              begin
                RectList[i, j].count := 0;
              end;


          end;
      end;
  setlength(path, 255);
  maxfillcount := 50;

  for i := 0 to w_r - 1 do
    for j := 0 to h_r - 1 do
      begin
        fillcount := 0;
        getFill(i, j, pt_1, maxfillcount + 1, path, fillcount);
        if fillcount <= maxfillcount then
          begin
            for idx := 0 to fillcount - 1 do
              begin
                RectList[path[idx].X, path[idx].y].count := 0;
              end;
          end;
      end;
  setlength(pt_1, 0);
  setlength(path, 0);


  Pcount := 0;
  for x := 1 to w - 2 do
    for y := 1 to h - 2 do
      begin
        if blist_diff[x, y] > 0 then
          inc(Pcount);
      end;
  c32.ARGB := clRed32;
  for x := 0 to w - 1 do
    for y := 0 to h - 1 do
      begin
        i := x div (r_count);
        j := y div (r_count);
        if RectList[i, j].count > 0 then
          c32.A := blist_diff[x, y]
        else
          c32.A := 0;
        bmp2.Pixel[x, y] := c32.ARGB;
      end;
  bmp2.DrawMode := dmBlend;
  for i := 0 to w_r - 1 do
    for j := 0 to h_r - 1 do
      begin
        if RectList[i, j].count > 0 then
          img.FrameRectS(RectList[i, j].rect, clBlue32);
      end;
  img.Draw(0, 0, bmp2);
  FreeAndNil(bmp2);

  for x := 0 to w - 1 do
    SetLength(blist[x], 0);
  SetLength(blist, 0);
  for x := 0 to w - 1 do
    SetLength(blist_diff[x], 0);
  SetLength(blist_diff, 0);
  for x := 0 to w_r - 1 do
    SetLength(RectList[x], 0);
  setlength(RectList, 0);
end;

完整代码 

unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, jpeg, gr32, ExtCtrls, StdCtrls;typeTForm1 = class(TForm)ScrollBox1: TScrollBox;Panel1: TPanel;Image1: TImage;ComboBox1: TComboBox;procedure FormCreate(Sender: TObject);private{ Private declarations }public{ Public declarations }end;varForm1: TForm1;implementation{$R *.dfm}
uses math;
typeTByteTable = array of array of Byte;TRectRec = recordrect: TRect;b: Byte;sum: integer;count: integer;end;function getsum(table: TByteTable; ax, ay, ix, iy, count: integer): integer;
vari, x, y: integer;
beginResult := 0;x := ax;y := ay;for i := 1 to count dobegininc(Result, table[x, y]);inc(x, ix);inc(y, iy);end;Result := Result div count;
end;procedure makeTable(img: TBitmap32);
varw, h, w_r, h_r, x, y, k, r_count, Pcount: Integer;bmp2, bmp: TBitmap32;blist: TByteTable;blist_diff: TByteTable;b, b1, b2, maxa: byte;c32: TColor32Entry;sum, stepCount, count: integer;idx, i, j, s_x_1, s_x_2: integer;s_y_1, s_y_2: integer;c_b: array[0..255] of integer;FilterB: Byte;Filter_Count: integer;Filter_Sum: integer;RectList: array of array of TRectRec;r: Trect;pt_1, path: array of TPoint;fillcount, maxfillcount: integer;function check_r(i, j: integer; pt: array of TPoint): Boolean;varidx: integer;beginResult := false;if RectList[i, j].count <= 0 thenexit;for idx := 0 to high(pt) dobeginif RectList[i + pt[idx].X, j + pt[idx].y].count > 0 thenbeginResult := false;Exit;end;end;Result := true;end;procedure getFill(x, y: integer; pt: array of TPoint; MaxCount: integer; var path: array of TPoint; var count: integer);varidx: integer;ax, ay: integer;beginif x < 0 thenExit;if y < 0 thenExit;if x >= w_r thenExit;if y >= h_r thenExit;if RectList[x, y].count <= 0 thenExit;if count >= MaxCount thenexit;for idx := count - 1 downto 0 dobeginif (path[idx].X = x) and (path[idx].y = y) thenbeginExit;end;end;path[count] := Point(x, y);inc(count);if count >= MaxCount thenexit;for idx := 0 to high(pt) dobeginax := x + pt[idx].X;ay := y + pt[idx].Y;getFill(ax, ay, pt, MaxCount, path, count);end;end;
beginw := img.Width;h := img.Height;SetLength(blist, w);for x := 0 to w - 1 doSetLength(blist[x], h);SetLength(blist_diff, w);for x := 0 to w - 1 doSetLength(blist_diff[x], h);for x := 0 to w - 1 dofor y := 0 to h - 1 dobeginc32.ARGB := img.Pixel[x, y];b := (77 * c32.R + 150 * c32.G + 29 * c32.B) shr 8;blist[x, y] := b;end;bmp2 := TBitmap32.Create;bmp2.SetSize(w, h);maxa := 0;stepCount := 5;for x := 0 to w - 1 dofor y := 0 to h - 1 dobegincount := min(x - 0 + 1, stepCount);s_x_1 := getsum(blist, x, y, -1, 0, count);count := min(w - x, stepCount);s_x_2 := getsum(blist, x, y, 1, 0, count);count := min(y - 0 + 1, stepCount);s_y_1 := getsum(blist, x, y, 0, -1, count);count := min(h - y, stepCount);s_y_2 := getsum(blist, x, y, 0, 1, count);b := max(abs(s_x_1 - s_x_2), abs(s_y_1 - s_y_2));blist_diff[x, y] := b;if b > maxa thenmaxa := b;end;ZeroMemory(@(c_b[0]), length(c_b) * sizeof(i));Pcount := 0;for x := 0 to w - 1 dofor y := 0 to h - 1 dobeginb := blist_diff[x, y];b := 255 * b div maxa;blist_diff[x, y] := b;inc(c_b[b]);inc(Pcount);end;FilterB := 0;count := 0;for i := 0 to 255 dobegininc(count, c_b[i]);if count > (Pcount div 2) thenbeginFilterB := i ;Break;endend;Pcount := 0;for x := 0 to w - 1 dofor y := 0 to h - 1 dobeginif blist_diff[x, y] < FilterB thenblist_diff[x, y] := 0;end;x := 0;y := 0;r_count := 10;w_r := (w - 1) div r_count + 1;h_r := (h - 1) div r_count + 1;SetLength(RectList, w_r);for x := 0 to w_r - 1 doSetLength(RectList[x], h_r);for i := 0 to w_r - 1 dofor j := 0 to h_r - 1 dobeginx := (i) * r_count;y := (j) * r_count;r.Left := x;r.Top := y;r.Right := Min(x + r_count, w);r.Bottom := Min(y + r_count, h);RectList[i, j].rect := r;RectList[i, j].sum := 0;RectList[i, j].count := 0;end;count := 0;sum := 0;for x := 0 to w - 1 dofor y := 0 to h - 1 dobeginb := blist_diff[x, y];if b = 0 thenContinue;i := x div (r_count);j := y div (r_count);inc(RectList[i, j].sum, b);inc(RectList[i, j].count);inc(sum, b);inc(count);end;Filter_Sum := sum div count;Filter_Count := max(r_count, count div (w_r * h_r));setlength(pt_1, 8);pt_1[0] := Point(-1, -1);pt_1[1] := Point(0, -1);pt_1[2] := Point(+1, -1);pt_1[3] := Point(-1, 0);pt_1[4] := Point(+1, 0);pt_1[5] := Point(-1, +1);pt_1[6] := Point(0, +1);pt_1[7] := Point(-1, +1);for i := 0 to w_r - 1 dofor j := 0 to h_r - 1 dobeginif RectList[i, j].count < Filter_Count thenbeginRectList[i, j].count := 0endelsebeginif RectList[i, j].sum < (Filter_Sum * RectList[i, j].count) thenbeginRectList[i, j].count := 0;end;end;end;setlength(path, 255);maxfillcount := 50;for i := 0 to w_r - 1 dofor j := 0 to h_r - 1 dobeginfillcount := 0;getFill(i, j, pt_1, maxfillcount + 1, path, fillcount);if fillcount <= maxfillcount thenbeginfor idx := 0 to fillcount - 1 dobeginRectList[path[idx].X, path[idx].y].count := 0;end;end;end;setlength(pt_1, 0);setlength(path, 0);Pcount := 0;for x := 1 to w - 2 dofor y := 1 to h - 2 dobeginif blist_diff[x, y] > 0 theninc(Pcount);end;c32.ARGB := clRed32;for x := 0 to w - 1 dofor y := 0 to h - 1 dobegini := x div (r_count);j := y div (r_count);if RectList[i, j].count > 0 thenc32.A := blist_diff[x, y]elsec32.A := 0;bmp2.Pixel[x, y] := c32.ARGB;end;bmp2.DrawMode := dmBlend;for i := 0 to w_r - 1 dofor j := 0 to h_r - 1 dobeginif RectList[i, j].count > 0 thenimg.FrameRectS(RectList[i, j].rect, clBlue32);end;img.Draw(0, 0, bmp2);FreeAndNil(bmp2);for x := 0 to w - 1 doSetLength(blist[x], 0);SetLength(blist, 0);for x := 0 to w - 1 doSetLength(blist_diff[x], 0);SetLength(blist_diff, 0);for x := 0 to w_r - 1 doSetLength(RectList[x], 0);setlength(RectList, 0);
end;procedure TForm1.FormCreate(Sender: TObject);
varfn: string;bmp: TBitmap32;
beginfn := ExtractFilePath(Application.ExeName) + 'IMG_0023.JPG';bmp := TBitmap32.Create;bmp.LoadFromFile(fn);fn := fn + '.bmp';makeTable(bmp);bmp.SaveToFile(fn);Image1.Picture.LoadFromFile(fn);
end;end.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/857528.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日一题——冒泡排序

C语言——冒泡排序 冒泡排序练习 前言&#xff1a;CSDN的小伙伴们&#xff0c;大家好&#xff01;今天我来给大家分享一种解题思想——冒泡排序。 冒泡排序 冒泡法的核心思想&#xff1a;两两相邻的元素进行比较 2.冒泡排序的算法描述如下。 (1)比较相邻的元素。如果第一 个比…

展讯-源码编译

1.硬件要求 编译主机要求&#xff0c;注意尽量不要使用虚拟机 CPU&#xff1a;Intel(R) Core(TM) i7-4790 CPU 3.60 GHz 内存&#xff1a;8G 硬盘&#xff1a;500G SSD Ubuntu 版本&#xff1a;Ubuntu 64-bit 14.04.5 LTS 这是最低版本要求&#xff0c;实际性能越高越好 2…

【机器学习 复习】 第1章 概述

一、概念 1.机器学习是一种通过先验信息来提升模型能力的方式。 即从数据中产生“模型”( model )的算法&#xff0c;然后对新的数据集进行预测。 2.数据集&#xff08;Dataset&#xff09;&#xff1a;所有数据的集合称为数据集。 训练集&#xff1a;用来训练出一个适合模…

wpfui:一个开源免费具有现代化设计趋势的WPF控件库

wpfui介绍 wpfui是一款开源免费&#xff08;MIT协议&#xff09;具有现代化设计趋势的WPF界面库。wpfui为wpf的界面开发提供了流畅的体验&#xff0c;提供了一个简单的方法&#xff0c;让使用WPF编写的应用程序跟上现代设计趋势。截止写这篇文章&#xff0c;该项目获得了6.7k …

YYU-5/80-260mm型钢筋残余变形测试仪 电子引伸计

YYU-5/80-260mm型钢筋接头专用引伸计&#xff0c;是按照《JGJ 107 2010 钢筋技术连接技术规程》的技术要求设计的&#xff0c;专门用于测试钢筋接头残余变形的双向平均引伸计&#xff0c;其标距可以根据钢筋直径要求进行调整。 完全符合《JGJ 107 2010 钢筋技术连接技术规程》…

信创适配评测

概叙 信创科普参考&#xff1a;全面国产化之路-信创-CSDN博客 有必要再解释一下两个名词“28N”&#xff0c;“79号文件”&#xff0c;因为“28N”指定了由政府牵头从各领域开启国产化的基调&#xff0c;而“79号文件”则指定了国产化的截止日期2027年。 信创的本质是实现中国信…

EOS black灵魂回响黑色无法联机/联机报错/联机失败怎么办

灵魂回响黑色EOS black中的职业系统&#xff0c;自由度非常高。从人物属性的精细调整&#xff0c;到装备属性的独特搭配&#xff0c;再到技能的个性化组合&#xff0c;每一步都充满了无限可能。更为惊喜的是&#xff0c;游戏中的角色职业不是一成不变的&#xff0c;而是随着手中…

Springboot3.3 整合Cassandra 4.1.5

一、数据库搭建 -- 创建Keyspace CREATE KEYSPACE school WITH replication {class:SimpleStrategy, replication_factor : 1};-- 创建表 CREATE TABLE student(id int PRIMARY KEY, name text, age int, genders int, address text ,interest set<text>,phone lis…

【C++】关于代码编译自动更新版本的问题

在写代码的时候&#xff0c;总是需要添加一个版本号&#xff0c;用于后续的版本管理 我常遇到的一个问题是&#xff0c;开发过程中&#xff0c;不一定会记得这件事情&#xff0c;导致有时候会出现同样的版本 于是希望有一个方式&#xff0c;能在编译代码的时候自动生成一个版…

【Proteus仿真】【Arduino单片机】汽车倒车报警系统设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduinno单片机控制器&#xff0c;使用LCD1602液晶、按键、继电器电机模块、DS18B20温度传感器、蜂鸣器LED、HCSR04超声波等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD16…

【网络安全学习】漏洞扫描:-04- ZAP漏洞扫描工具

**ZAP(Zed Attack Proxy)**是一款由OWASP组织开发的免费且开源的安全测试工具。 ZAP支持认证、AJAX爬取、自动化扫描、强制浏览和动态SSL证书等功能。 1️⃣ 安装zap工具 现在的kali版本不一定会预装zap&#xff0c;我们可以自行安装&#xff0c;安装也十分简单。 apt-get …

mybatis查询PostgreSQL报错:无法确定参数 $1 的数据类型

错误信息 ### Cause: org.postgresql.util.PSQLException: 错误: 无法确定参数 $1 的数据类型 ; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: 错误: 无法确定参数 $1 的数据类型] with root cause org.postgresql.util.PSQLException: 错误: …

转让中字头无区域农业公司变更快包迁全国

国家局名称的公司不仅可以提升企业形象&#xff0c;还能展现公司的实力。由于国家总局核名的审核标准相对严格&#xff0c;能够通过核名的企业一般都具备一定的实力和资质。因此&#xff0c;选择国家局核名的企业往往能够在市场中获得更多信任和认可。详情致电咨询我或者来公司…

C# 实现draw一个简单的温度计

运行结果 概述&#xff1a; 代码分析 该控件主要包含以下几个部分&#xff1a; 属性定义&#xff1a; MinValue&#xff1a;最低温度值。 MaxValue&#xff1a;最高温度值。 CurrentValue&#xff1a;当前温度值。 构造函数&#xff1a; 设置了一些控件样式来提升绘制效果…

【计算机网络体系结构】计算机网络体系结构实验-DHCP实验

服务器ip地址 2. 服务器地址池 3. 客户端ip 4. ping Ipconfig

【计算机网络仿真】b站湖科大教书匠思科Packet Tracer——实验7 虚拟局域网VLAN

一、实验目的 1.学习如何划分VLAN&#xff1b; 2.验证划分VLAN的作用&#xff1b; 3.学习如何用命令行创建VLAN&#xff0c;将端口划分到VLAN&#xff0c;设置端口类型。 二、实验要求 1.使用Cisco Packet Tracer仿真平台&#xff1b; 2.观看B站湖科大教书匠仿真实验视频&am…

3d中模型显示黑色给不了材质---模大狮模型网

如果3D模型显示黑色&#xff0c;而且无法给它添加材质&#xff0c;可能有以下几种原因&#xff1a; 一&#xff1a;模型没有UV贴图 UV贴图是3D模型表面纹理的一种方式&#xff0c;如果模型没有正确的UV贴图&#xff0c;渲染时可能会显示黑色。在大多数3D建模软件中&#xff0c…

qml:一个基础的界面设计

文章目录 1、文章说明2、效果图3、重要代码说明3.1 组件切换开关下拉框矩形卡片 3.2 窗口最大化后组件全部居中3.3 菜单栏3.4 Repeater实现重复8行3.5 图片加载直接加载图片文本转图片FluentUI中可供选择的图标 1、文章说明 qt6.5.3 qml写的一个界面配置设计软件&#xff0c;目…

算法设计与分析:动态规划法求扔鸡蛋问题 C++

目录 一、实验目的 二、问题描述 三、实验要求 四、算法思想和实验结果 1、动态规划法原理&#xff1a; 2、解决方法&#xff1a; 2.1 方法一&#xff1a;常规动态规划 2.1.1 算法思想&#xff1a; 2.1.2 时间复杂度分析 2.1.3 时间效率分析 2.2 方法二&#xff1a;动态规划加…

python数据分析-糖尿病数据集数据分析预测

一、研究背景和意义 糖尿病是美国最普遍的慢性病之一&#xff0c;每年影响数百万美国人&#xff0c;并对经济造成重大的经济负担。糖尿病是一种严重的慢性疾病&#xff0c;其中个体失去有效调节血液中葡萄糖水平的能力&#xff0c;并可能导致生活质量和预期寿命下降。。。。 …