导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
cnj79 (仙南)
★☆☆☆☆
-
盒子活跃会员
2019/4/7 9:58:45
标题:
求多边形区域的像素总和,请各位能指点一下思路。
浏览:1621
加入我的收藏
楼主:
如图片中,想计算多边形中的树叶的总像素,多边形由CreatePolygonRgn给出,然后SelectClipRgn到Bitmap中,这样Bitmap中没有图形中的地方显示白色。现在的思路是Scanline整个Bitmap,统计白色像素的个数,然后Bitamp的Width*Height-白色像素得出图片中的有效像素总和,感觉这种方法效率不好,因为多边形区域中如果也有白色像素的话,结果就不准确了。现在想问下大家,有没有更好办法计算有效像素总和,谢谢。
此帖子包含附件: 大小: 65.8K
----------------------------------------------
-
作者:
2019/4/7 13:03:58
1楼:
https://www.cnblogs.com/TenosDoIt/p/4047211.html https://www.cnblogs.com/xiexinxinlove/p/3708147.html
----------------------------------------------
-
作者:
2019/4/7 20:55:00
2楼:
你都CreatePolygonRgn创建了多边形了,还Scanline去遍历?
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2019/4/8 9:05:30
3楼:
楼上正解。 你建立的时候,就已经知道 这个 多边形的各个边长了。
----------------------------------------------
(C)(P)Flying Wang
作者:
cnj79 (仙南)
★☆☆☆☆
-
盒子活跃会员
2019/4/8 11:17:06
4楼:
可能我的意思没表达清楚,其实是想知道多边形里面某个颜色占多边形总面积的百分比。由于多边形外面是白色像素,Scanline时每一行需要将白色像素排除在外,并且计算该行的有效像素个数,同时计算某个颜色的个数,扫描完图形后累计某个颜色的总数,有效像素总数,相除后得出百分比。这样就产生一个问题,如果多边形里面也有白色像素的话,结果就不准确。或者更简单的说是想知道,某一点是否在某一区域里的简单算法。
此帖子包含附件: 大小: 34.3K
----------------------------------------------
-
作者:
2019/4/8 11:50:46
5楼:
简单的说 知道 边长 就一定能求出面积的。
----------------------------------------------
(C)(P)Flying Wang
作者:
2019/4/8 11:54:00
5楼:
TPoint2f = record x, y: single; end; TPolygon = record Values: array of TPoint2f; public function Contains(const APoint: TPoint2f): Boolean; end; { TPolygon } function TPolygon.Contains(const APoint: TPoint2f): Boolean; var N, Counter , I : Integer; XInters : Real; P1, P2 : TPoint2f; begin N := High(Self.Values); Counter := 0; P1 := Self.Values[0]; for I := 1 to N do begin P2 := Self.Values[I mod N]; if APoint.y > Min(P1.y, P2.y) then if APoint.y <= Max(P1.y, P2.y) then if APoint.x <= Max(P1.x, P2.x) then if P1.y <> P2.y then begin XInters := (APoint.y - P1.y) * (P2.x - P1.x) / (P2.y - P1.y) + P1.x; if (P1.x = P2.x) or (APoint.x <= XInters) then Inc(Counter); end; P1 := P2; end; Result := (Counter mod 2 <> 0); end;
----------------------------------------------
虽千万人吾往矣!
作者:
cnj79 (仙南)
★☆☆☆☆
-
盒子活跃会员
2019/4/8 13:00:11
6楼:
谢谢楼上的代码,但你这只是判断一个点是否在多边形区域里。我如果要计算多边形区域中的某个像素的百分比的话,还是需要遍历图形,多次调用该代码进行计算。这是一种方法,如果有更快捷的方法更好。
----------------------------------------------
-
作者:
2019/4/8 13:43:42
7楼:
简单的说 如果你已经获得了 Bitmap 就不考虑什么 多边形了。 就是一个矩形。 Bitmap 的内容,就是一个内存块。 内存的处理,除了循环别无它法。爱信不信。
----------------------------------------------
(C)(P)Flying Wang
作者:
cnj79 (仙南)
★☆☆☆☆
-
盒子活跃会员
2019/4/8 22:24:12
8楼:
想来想去,为了简单点,打算用以下方法: 1.CreatePolygonRgn在图形上建立多边形区域 2.计算多边形的矩形区域,建立一个相同大小的32位Bitmap,设置所有像素透明度为0 3.SelectClipRgn将多边形区域中的图像Copy到Bitmap中 4.Scanline每一行,逐个判断每个像素,透明度为0则为空白,非0则为有效像素总数+1,接着判断该有效像素如果RGB=某颜色则某颜色数量+1 5.统计某个颜色数量 / 有效像素总数,得出百分比
----------------------------------------------
-
作者:
2019/4/9 11:55:44
9楼:
重点是 Scanline 函数的 速度。 试试 获取到 整个内存块。也许 会更快。
----------------------------------------------
(C)(P)Flying Wang
作者:
2019/4/9 13:18:33
10楼:
简单地说, 将白色换成某种稀奇古怪的不可能在图形中出现的颜色不就搞定了, 通常选择最高纯度亮度的紫红色
----------------------------------------------
-
作者:
cnj79 (仙南)
★☆☆☆☆
-
盒子活跃会员
2019/4/9 19:20:41
11楼:
Scanline的速度不是关键,因为多边形矩形区域一般不超过400*200。其实我倾向于直接在原图上计算,这样省了一个中间的Bitmap。由于多边形区域的矩形范围里有些点并不在多边形里面,不应该参与计算,这样就得逐个像素判断该点是否在多边形里,计算量可能有点大。 1.将多边形区域图像拷贝在特殊背景颜色的Bitmap中,逐点比较颜色RGB值,RGB不等于指点的颜色则参与计算 2.将多边形区域的矩形范围里逐点判断是否在多边形里,在则参与计算。 这是目前能想到的两种办法了。
----------------------------------------------
-
作者:
cnj79 (仙南)
★☆☆☆☆
-
盒子活跃会员
2019/4/9 21:48:54
12楼:
如果能直接遍历多边形区域每一个像素那样最简单了,因为遍历多边形区域相同大小的矩形区域还得考虑那些不在多边形区域的无效像素,可惜没有头绪。
----------------------------------------------
-
作者:
2019/4/12 9:36:24
13楼:
网上搜:计算不同颜色面积 类似的
----------------------------------------------
-
作者:
2019/4/12 10:18:35
14楼:
可以考虑一下用扫描线算法来求解。
----------------------------------------------
-
作者:
2019/4/12 11:11:12
15楼:
用总面积除以树叶多边形面积再乘以总面的像素
----------------------------------------------
-
作者:
cnj79 (仙南)
★☆☆☆☆
-
盒子活跃会员
2019/4/12 19:19:59
16楼:
可能大家都没理解我的需求,我是想如何快速遍历多边形区域,并对其中的像素颜色进行计算和统计。难就难在如何快速遍历多边形区域,现在暂时用下面这种方法,以后有好的算法再优化。 procedure TForm1.Button1Click(Sender: TObject); var Rgn: HRGN; {区域句柄} RgnDataSize: Integer; {区域数据缓冲区的大小} RgnData: PRgnData; {区域数据指针} Count: Integer; {区域中的矩形总数} Rect: PRect; {矩形指针} i, j, k, t: Integer; begin {建立一个圆角矩形区域} Rgn := CreateEllipticRgn(10,10,250,250); {获取区域数据缓冲区的大小, 并申请需要的内存} RgnDataSize := GetRegionData(Rgn, 0, nil); GetMem(RgnData, RgnDataSize); {再次使用 GetRegionData, 获取区域数据} GetRegionData(Rgn, RgnDataSize, RgnData); {获取矩形总数} Count := RgnData^.rdh.nCount; {获取第一个矩形的指针} Rect := @RgnData^.Buffer; {枚举区域中的矩形, 并使用随机颜色画出来} Randomize; for i := 0 to Count - 1 do begin for j := Rect^.Top to Rect^.Bottom do for k := Rect^.Left to Rect^.Right do Canvas.Pixels[k, j] := Random($FFFFFF); Inc(Rect); {指向下一个矩形} end; {释放资源} //DeleteObject(BrushHandle); DeleteObject(Rgn); FreeMem(RgnData); end;
----------------------------------------------
-
作者:
2019/4/14 11:28:31
17楼:
搞得太复杂。你有多少像素啊? 直接对整个图片扫描每个像素,简单直接。想要速度,把 Delphi 的并行计算加上啊。跑个多核CPU,速度马上翻倍。
----------------------------------------------
-
作者:
2019/4/15 14:21:35
18楼:
楼主应该根据给定的矩形(10,10,250,250),求出该矩形的内切圆/椭圆方程, 如果矩形长为2a宽为2b,那么椭圆的标准方程是x2/a2﹢y2/b2=1,数学知识不 太记得了,然后再扫描矩形里面的每一点,然后再与那个圆方程进行判断,判断 该点是在圆外,还是圆上,还是圆内。
----------------------------------------------
-
作者:
cnj79 (仙南)
★☆☆☆☆
-
盒子活跃会员
2019/4/15 20:39:02
19楼:
实际上选择的区域是多边形,圆只是举例说明。扫描全图没有意义,因为参与计算的范围不需要全图。 可能这个问题没有捷径可走,只能想办法给多边形区域像素加上特殊标记,这样扫描时可以简单的判断该像素是否在多边形里面。
----------------------------------------------
-