好久不搞delphi一搞就出问题.问题解决立刻给分.

风平心境 2010-07-31 09:35:08

{-----------------------------------------------------------------------------
Unit Name: PublicFunction
Author:
Purpose: 图像处理公用函数
History:
-----------------------------------------------------------------------------}

unit PublicFunction;

interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics,Jpeg,GIFImage,Math;
type
TPixels = Array of array of TRGBTriple;
TPixelArray = Array of TRGBTriple;
TPixelChanncle=(tcRed,tcGreen,tcBlue);

procedure GraphicMedianFilter(var bit: TBitmap;matrix_x,matrix_y:integer);
procedure ReadPixelArray(Pic: Tbitmap;rec:TRect; var tPix: TPixelArray);
procedure SortPixelArray(var A: TPixelArray; iLo, iHi: Integer;c:TPixelChanncle );

implementation


{-----------------------------------------------------------------------------
Procedure: ReadPixelArray
Author:
Date: 31-七月-2010
Arguments: Pic: Tbitmap;rec:TRect; var tPix: TPixelArray
Result: None
Description: 读取图片内的矩形区域的像素 返回 TPixelArray 像素-维数组
-----------------------------------------------------------------------------}
procedure ReadPixelArray(Pic: Tbitmap;rec:TRect; var tPix: TPixelArray);
Var PixPtr:PbyteArray;
i,j,m,rec_H,rec_W,n,index,len :Integer;
begin
rec_H:=Min(rec.Bottom,Pic.Height-1);
rec_W:=Min(rec.Right,pic.Width-1);
len:=(rec_H+1-Max(rec.Top,0))*(rec_W+1-Max(rec.Left,0));
SetLength(tPix,len);
Pic.PixelFormat := pf24bit;
Pic.HandleType:=bmDIB;
index:=0;
For i :=Max(rec.Top,0) to rec_H do
begin
PixPtr:=Pic.ScanLine[i];
for j:= Max(rec.Left,0) to rec_W do
begin
m := j*3;
n:= index*rec_H+j;
tPix[n].rgbtBlue := PixPtr[m];
tPix[n].rgbtGreen := PixPtr[m+1];
tPix[n].rgbtRed := PixPtr[m+2];
end;
inc(index);
end;
end;

{-----------------------------------------------------------------------------
Procedure: GraphicMedianFilter
Author:
Date: 31-七月-2010
Arguments: var bit: TBitmap,matrix_x,matrix_y:integer
Result: None
Description: 区域中值滤波 按照:[matrix_x]*[matrix_y]矩阵大小
-----------------------------------------------------------------------------}
procedure GraphicMedianFilter(var bit: TBitmap;matrix_x,matrix_y:integer);
var
x, y: integer;
bitmap: Tbitmap;
p: pbyteArray;
pix:TRGBTriple;
procedure OffsetRect(var r:TRect;x,y:integer);
begin
r.Left :=r.Left +x;
r.Top :=r.Top +y;
r.Bottom:=r.Bottom +y;
r.Right :=r.Right +x;
end;
//求出区域的中值像素
function calMean(x,y:integer):TRGBTriple;
var pixels:TPixelArray;
r:TRect;
rpix:TRGBTriple;
len,x1,y1,n,m:integer;
begin
r:=Rect(x,y,x+matrix_x-1,y+matrix_y-1);
//平移
x1:=Round(matrix_x/2)-1;
y1:=Round(matrix_y/2)-1;
OffsetRect(r,-x1,-y1);

//读矩形内的像素到数组 pixels
ReadPixelArray(bit,r,pixels);

len:=high(pixels);
m:=Round(len/2);
//排序数组并取出中值
SortPixelArray(pixels,0,len,tcRed);
rpix.rgbtRed:=pixels[m].rgbtRed;
SortPixelArray(pixels,0,len,tcGreen);
rpix.rgbtGreen:=pixels[m].rgbtGreen;
SortPixelArray(pixels,0,len,tcBlue);
rpix.rgbtBlue:=pixels[m].rgbtBlue;
setLength(pixels,0);
pixels:=nil;
result:= rpix;
end;
begin
if (matrix_x<3) or (matrix_y<3) then exit;
bitmap:=TBitMap.Create;
bitmap.Assign(bit);
for y := 0 to bitmap.Height - 1 do
begin
P := bitmap.ScanLine[y];
for x := 0 to bitmap.Width - 1 do
begin
pix:= calMean(x,y);
p[3 * x + 2] := pix.rgbtRed;
p[3 * x + 1] := pix.rgbtGreen;
p[3 * x ] := pix.rgbtBlue;
end;
end;
bit.Assign(bitmap);
bitmap.Free;
end;

{-----------------------------------------------------------------------------
Procedure: SortArray
Author:
Date: 31-七月-2010
Arguments: var A: array of Integer; iLo, iHi: Integer;c:TPixelChanncle
Result: None
Description: 像素数组排序
-----------------------------------------------------------------------------}
procedure SortPixelArray(var A: TPixelArray; iLo, iHi: Integer;c:TPixelChanncle );
var
Lo, Hi, Mid, T: Integer;
begin
Lo := iLo;
Hi := iHi;
case c of
tcRed: Mid := A[(Lo + Hi) div 2].rgbtRed;
tcGreen:Mid := A[(Lo + Hi) div 2].rgbtGreen;
tcBlue: Mid := A[(Lo + Hi) div 2].rgbtBlue;
end;
repeat
case c of
tcRed:
begin
while A[Lo].rgbtRed < Mid do Inc(Lo);
while A[Hi].rgbtRed > Mid do Dec(Hi);
if Lo <= Hi then
begin
T := A[Lo].rgbtRed;
A[Lo].rgbtRed := A[Hi].rgbtRed;
A[Hi].rgbtRed := T;
Inc(Lo);
Dec(Hi);
end;
end;
tcGreen:
begin
while A[Lo].rgbtGreen < Mid do Inc(Lo);
while A[Hi].rgbtGreen > Mid do Dec(Hi);
if Lo <= Hi then
begin
T := A[Lo].rgbtGreen;
A[Lo].rgbtGreen := A[Hi].rgbtGreen;
A[Hi].rgbtGreen := T;
Inc(Lo);
Dec(Hi);
end;
end;
tcBlue:
begin
while A[Lo].rgbtBlue < Mid do Inc(Lo);
while A[Hi].rgbtBlue > Mid do Dec(Hi);
if Lo <= Hi then
begin
T := A[Lo].rgbtBlue;
A[Lo].rgbtBlue := A[Hi].rgbtBlue;
A[Hi].rgbtBlue :=T;
Inc(Lo);
Dec(Hi);
end;
end;
end;
until Lo > Hi;
if Hi > iLo then SortPixelArray(A, iLo, Hi,c);
if Lo < iHi then SortPixelArray(A, Lo, iHi,c);
end;
end.


窗口端调用

procedure TForm1.Button9Click(Sender: TObject);
var bmp:TBitmap;
begin
bmp:=TBitmap.Create();
bmp.Assign(image1.Picture.Bitmap);
GraphicMedianFilter(bmp,3,3);
image2.Picture.Bitmap:=bmp;
end;


以上setLength(pixels,0);是出错的地方.地址错误.而且这个错误每张图片都是不固定的.
按正常一个局部动态数组在函数调用结束会调用用_DnyArrayClear清理函数. 错误就发生这个函数: Invalid pointer operation 奇怪.用的好好的,系统清理动态数组就出错.那位好心人帮我调调. 郁闷想多给分都不行



...全文
370 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
风平心境 2010-08-16
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 mwy654321 的回复:]

好久不搞delphi一搞就出问题。

出问题与你是否经常搞delphi无关。
[/Quote]
我也想知道自己的问题出来在哪里?
风平心境 2010-08-16
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 iamduo 的回复:]

if (matrix_x<3) or (matrix_y<3) then exit;
bitmap:=TBitMap.Create;
bitmap.Assign(bit);
for y := 0 to bitmap.Height - 1 do
begin
P := bitmap.ScanLine[y];
for ……
[/Quote]
这个有什么区别吗?
bit.Assign(bitmap);
能所一下原因吗?代码我已经改成TList了. 原来版本就没保存了.不好意思
风平心境 2010-08-16
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 weirdman 的回复:]

前几天我也遇到过相同问题
我的是图片像素读错了,导致存进数组的为空值
所以虽然他提示是setLength(pixels,0)
建议你检查下前面的像素读取有没错误
[/Quote]
像素数组读取是没错的.用这个方法读出来的像素数组实现其他的filter了.我改成TList就没这个问题了.所以才抓狂.
gusman 2010-08-16
  • 打赏
  • 举报
回复
学习!
iamduo 2010-08-03
  • 打赏
  • 举报
回复
if (matrix_x<3) or (matrix_y<3) then exit;
bitmap:=TBitMap.Create;
bitmap.Assign(bit);
for y := 0 to bitmap.Height - 1 do
begin
P := bitmap.ScanLine[y];
for x := 0 to bitmap.Width - 1 do
begin
pix:= calMean(x,y);
p[3 * x + 2] := pix.rgbtRed;
p[3 * x + 1] := pix.rgbtGreen;
p[3 * x ] := pix.rgbtBlue;
end;
end;
bit.Assign(bitmap);
bitmap.Free;


试试看,把bitmap 变量删掉。直接用 bit 是否会错?
无条件为你 2010-08-03
  • 打赏
  • 举报
回复
好久不搞delphi一搞就出问题。

出问题与你是否经常搞delphi无关。
weirdman 2010-08-03
  • 打赏
  • 举报
回复
前几天我也遇到过相同问题
我的是图片像素读错了,导致存进数组的为空值
所以虽然他提示是setLength(pixels,0)
建议你检查下前面的像素读取有没错误
风平心境 2010-08-02
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 wdonghai 的回复:]

楼主去看一下DELPHI数字图像处理这本书中的第五章,里面就有个中值滤波处理
[/Quote] 问题不是在这里.那个不是我想要的代码.
这里主要问题是想知道为什么这样使用动态数组会有这样的错误.
  • 打赏
  • 举报
回复
帮你顶吧,那么多代码不敢看,发现你写的代码好工整!!!!!!!
奔雷手 2010-08-02
  • 打赏
  • 举报
回复
膜拜~~~~
wdonghai 2010-08-02
  • 打赏
  • 举报
回复
楼主去看一下DELPHI数字图像处理这本书中的第五章,里面就有个中值滤波处理
sghff110 2010-08-02
  • 打赏
  • 举报
回复
我也顶一下。
风平心境 2010-08-01
  • 打赏
  • 举报
回复
算了把数组改成Tlist 了. 想必是由于动态数组释放时候它里面的某些项目已经释放了.
风平心境 2010-08-01
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 sqldebug_fan 的回复:]
PixPtr:PbyteArray改成PixPtr:TbyteArray,SetLength接收的数组定义,不是动态数组指针,你试试。
[/Quote]

可是 PixPtr:=Pic.ScanLine[i]; 返回的是数组的指针再转成数组 应该不是这个问题吧.
我把
PixPtr:=Pic.ScanLine[i];
改成
PixPtr:= TbyteArray(Pic.ScanLine[i]^);
转不了啊...出错: EAccessViolation 地址访问错误.

"SetLength接收的数组定义" 由于是不定大小的矩形区域所以无法固定接收数组的大小.

SQLDebug_Fan 2010-08-01
  • 打赏
  • 举报
回复
PixPtr:PbyteArray改成PixPtr:TbyteArray,SetLength接收的数组定义,不是动态数组指针,你试试。
风平心境 2010-08-01
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 tjianliang 的回复:]
在这一句上面设个断点,看看pixels内容
[/Quote]
谢谢你的回答.
pixels 是可以访问,pixels前面用的好的. 错误出现在系统函数@DnyArrayClear里面. 在cpu里看出来的.

问题出现在这个子函数里面红色字.也就是函数结束部分
function calMean(x,y:integer):TRGBTriple;
var pixels:TPixelArray;
r:TRect;
rpix:TRGBTriple;
len,x1,y1,n,m:integer;
begin
r:=Rect(x,y,x+matrix_x-1,y+matrix_y-1);
//平移
x1:=Round(matrix_x/2)-1;
y1:=Round(matrix_y/2)-1;
OffsetRect(r,-x1,-y1);

//读矩形内的像素到数组 pixels
ReadPixelArray(bit,r,pixels);

len:=high(pixels);
m:=Round(len/2);
//排序数组并取出中值
SortPixelArray(pixels,0,len,tcRed);
rpix.rgbtRed:=pixels[m].rgbtRed;
SortPixelArray(pixels,0,len,tcGreen);
rpix.rgbtGreen:=pixels[m].rgbtGreen;
SortPixelArray(pixels,0,len,tcBlue);
rpix.rgbtBlue:=pixels[m].rgbtBlue;
setLength(pixels,0);
pixels:=nil;
result:= rpix;

end;
风平心境 2010-08-01
  • 打赏
  • 举报
回复
windows 单元 自带的.
  tagRGBTRIPLE = packed record
rgbtBlue: Byte;
rgbtGreen: Byte;
rgbtRed: Byte;
end;
TRGBTriple = tagRGBTRIPLE;
wxieyang 2010-08-01
  • 打赏
  • 举报
回复
TRGBTriple 结构是什么样子?
亮剑_ 2010-07-31
  • 打赏
  • 举报
回复
在这一句上面设个断点,看看pixels内容
内容概要:本文围绕“单相逆变器闭环逆变电路PWM模型仿真研究”展开,基于Simulink平台构建单相逆变器的闭环控制系统仿真模型,重点研究PWM调制技术在逆变电路中的应用与实现。文中详细阐述了系统架构设计、电压电流双闭环控制策略的实现原理、控制器参数设计及仿真建模全过程,并通过仿真结果验证了控制方案在动态响应、稳态精度与系统稳定性方面的有效性。同时,文档还涵盖多种电力电子系统典型应用场景,如多类型短路故障仿真(中性点不接地、经小电阻接地、经消弧线圈接地等)、软开关技术、微电网能量管理、MPPT控制等,体现较强的技术综合性和工程实践价值。; 适合人群:电气工程、自动化、电力电子与新能源等相关专业的高校本科生、研究生、科研人员,以及从事电力系统仿真、逆变器设计与新能源并网技术研发的工程技术人员。; 使用场景及目标:①掌握基于Simulink的单相逆变器闭环控制系统建模与PWM仿真方法;②深入理解双闭环控制、SPWM/SVPWM调制、系统稳定性析等核心技术原理;③为课程设计、毕业设计、科研项目或实际工程开发提供可复用的仿真模型与技术支持; 阅读建议:建议结合文中仿真模型动手实践,重点掌握PI控制器参数整定、PWM信号生成机制与仿真结果析方法,同时可延伸学习文档中涉及的软开关、故障仿真、微电网控制等关联技术,以拓展系统级设计能力。

1,184

社区成员

发帖
与我相关
我的任务
社区描述
Delphi GAME,图形处理/多媒体
社区管理员
  • GAME,图形处理/多媒体社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧