如何在一图片中找到特定的颜色?(100)

  • 主题发起人 dragon123
  • 开始时间
D

dragon123

Unregistered / Unconfirmed
GUEST, unregistred user!
一张图片中,如何将其中特定颜色的物体,比如红色,(比如红色的铅笔,红色的花朵),找出来,并将其标识出来,如果有相应的控件也行。谢谢
 
用Graphics32加一个三方单元GR32_SeedFill应该能实现
 
楼上能否具体说一下。其实就是一个颜色的标识的问题
 
就是一个颜色的种子填充问题你可以用GR32_SeedFill单元找出相应颜色的区域然后标识出区域就可以了可以给一段代码给你看一下其中CreateRegion函数是一个用指定图形的指定颜色建立一个区域procedure TMarchimage32.MagicMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);var SeedBmp: TSeedFill; DestBmp, SoureceBmp: TBitmap32; Bit: PColor32; Value: byte; Ptr: PByte; i, j: Integer; TempBmp: TBitmap; fileStream: TStream; BoundRgn: Hrgn;begin ChkDraw := False; if FRectMode = mmMove then begin if not ChkMove then begin DeleteObject(DrawHrgn); DrawHrgn := 0; end; ChkMove := False; FRectMode := mmNew; end else begin if Self.ScaleMode = smScale then begin SoureceBmp := TBitmap32.Create; SoureceBmp.SetSize(Trunc(Self.Bitmap.Width * Self.Scale), Trunc(Self.Bitmap.Height * Self.Scale)); SoureceBmp.Clear(clBlack32); Self.Bitmap.DrawMode := dmBlend; Self.Bitmap.DrawTo(SoureceBmp, SoureceBmp.ClipRect, Self.Bitmap.ClipRect); SeedBmp := TSeedFill.Create(SoureceBmp); end else SeedBmp := TSeedFill.Create(Self.Bitmap); SeedBmp.Min := Trunc(FTolerance / 100 * 255); SeedBmp.Max := SeedBmp.Min; X := (X div FCompartmentWidth) * FCompartmentWidth; Y := (Y div FCompartmentWidth) * FCompartmentWidth; SeedBmp.SetFillPoint(X, Y); SeedBmp.Update; DestBmp := TBitmap32.Create; if Self.ScaleMode = smScale then DestBmp.SetSize(SoureceBmp.Width, SoureceBmp.Height) else DestBmp.SetSize(Self.Bitmap.Width, Self.Bitmap.Height); Bit := @DestBmp.Bits[0]; for j := 0 to DestBmp.Height - 1 do for i := 0 to DestBmp.Width - 1 do begin Ptr := SeedBmp.ToleranceMaskPtr[i, j]; Value := Ptr^; Bit^ := $FF000000 or (Value shl 16) or (Value shl 8) or Value; Inc(Bit); end; SeedBmp.free; fileStream := TMemoryStream.Create; DestBmp.SaveToStream(fileStream); fileStream.Position := 0; TempBmp := TBitmap.Create; TempBmp.LoadFromStream(fileStream); fileStream.free; DestBmp.free; CurrHrgn := CreateRegion(TempBmp, clBlack, Handle); TempBmp.free; if Self.ScaleMode = smScale then SoureceBmp.free; if DrawHrgn <> 0 then begin DeleteObject(DrawHrgn); DrawHrgn := 0; end; DrawHrgn := CreateRectRgnIndirect(Rect(0, 0, 0, 0)); CombineRgn(DrawHrgn, DrawHrgn, CurrHrgn, RGN_OR); DeleteObject(CurrHrgn); CurrHrgn := 0; end; RemoveCursorRestrictions; RemoveBmp; if DrawHrgn <> 0 then begin BoundRgn := CreateRectRgnIndirect(Self.ClientRect); CombineRgn(DrawHrgn, DrawHrgn, BoundRgn, RGN_AND); DeleteObject(BoundRgn); ShowHrgn(DrawHrgn); end;end;
 
非常感谢楼上。本人对于图像方面了解很少,还望给予详尽解答。用Graphics32加一个三方单元GR32_SeedFill应该能实现 。这句话什么意思,Graphics32控件??GR32_SeedFill是什么??
 
Graphics32是一个控件GR32_SeedFill是国外一个人在Graphics32的基础上写的一个关天颜色填充的单元在网上找得到的
 
Graphics32控件已经安装,GR32_SeedFill也找到了,但是不知道怎么用。能否给写过可执行的例子?谢谢
 
代码上面都有你自已看一下我把CreateRegion函数的代码给你你自已再研究一下function CreateRegion(wMask: TBitmap; wColor: TColor; hControl: THandle): Hrgn;var dc, dc_c: HDC; rgn: Hrgn; X, Y: Integer; coord: TPoint; line: Boolean; Color: TColor;begin dc := GetWindowDC(hControl); dc_c := CreateCompatibleDC(dc); SelectObject(dc_c, wMask.Handle); BeginPath(dc); for X := 0 to wMask.Width - 1 do begin line := False; for Y := 0 to wMask.Height - 1 do begin Color := GetPixel(dc_c, X, Y); if not (Color = wColor) then begin if not line then begin line := true; coord.X := X; coord.Y := Y; end; end; if (Color = wColor) or (Y = wMask.Height - 1) then begin if line then begin line := False; MoveToEx(dc, coord.X, coord.Y, nil); LineTo(dc, coord.X, Y); LineTo(dc, coord.X + 1, Y); LineTo(dc, coord.X + 1, coord.Y); CloseFigure(dc); end; end; end; end; EndPath(dc); rgn := PathToRegion(dc); ReleaseDC(hControl, dc); Result := rgn;end;
 
同我告诉你的是一样的道理都是用颜色填充的方式实现的并且都是用GR32_SeedFill单元的你自已好好看一下他是用类的方式实现的
 
谢谢fang_csc。取色时由于是某一点的特定颜色,但是对于某肉眼观察为红色的物体,其实每一点的红色并不相同,但取色时过于精确,并不能把整个肉眼定为红色的整体物体标记出,还望帮忙。
 
将RGB转换为HSI可以解决这个问题吗?有没有关于转换hsi或者这类图像处理的控件?谢谢
 
找到一例子菜单open选取图片,菜单select-color range-选择image,然后从图片中点取所需的颜色,按ok似乎可以实现。于是想看一下ok按钮中所执行的代码,可是发现ok和cancel中都没有代码,ok中到底执行了什么,能否给看一下
 
其实图片的颜色很简单,就是蓝色和红色,但是肉眼的红色也有深浅只分,也有与蓝色混合的红色。如何将肉眼的红色界定一个范围?
 
procedure RGBtoHSL(R, G, B: Integer; var H, S, L: Integer);// RGB空间到HSL空间的转换var Delta: Double; CMax, CMin: Double; Red, Green, Blue, Hue, Sat, Lum: Double;begin Red := R / 255; Green := G / 255; Blue := B / 255; CMax := Max(Red, Max(Green, Blue)); CMin := Min(Red, Min(Green, Blue)); Lum := (CMax + CMin) / 2; if CMax = CMin then begin Sat := 0; Hue := 0; end else begin if Lum < 0.5 then Sat := (CMax - CMin) / (CMax + CMin) else Sat := (cmax - cmin) / (2 - cmax - cmin); delta := CMax - CMin; if Red = CMax then Hue := (Green - Blue) / Delta else if Green = CMax then Hue := 2 + (Blue - Red) / Delta else Hue := 4.0 + (Red - Green) / Delta; Hue := Hue / 6; if Hue < 0 then Hue := Hue + 1; end; H := Round(Hue * 360); S := Round(Sat * 100); L := Round(Lum * 100);end;
 
HSL的转换论坛上已经看到了,但是不知它和HSI是否一样,说法不一,有的说是有差别。此例图片只是蓝色背景中的红色,但是肉眼的蓝色和红色由于有深浅和红蓝混合的原因,所以不能只查找一点的颜色。我的想法是,1.找出所有肉眼蓝色(或红色)由深到浅的所有颜色2.找出由蓝到红混合形成的肉眼蓝红交界,界定蓝红的所有颜色。3.查找红色的颜色集(或去掉蓝色的颜色集)
 
建议楼主先了解位图BMP和DELPHI下的TBITMAP类处理你的问题,只有一个办法,扫描全像素(需注意:如果是8位256色图片,单个像素存储的不是颜色,是调色板的索引号)代码大概如下:var bmp:tbitmap;i,j:Integer;p:pcolor (24位图像)for j:=0 to bmp.height-1 do beginp:=bmp.scanline[j];for i:=0 to bmp.width-1 do begin if p^=yourcolor then .... inc(p); end;end;
 
if p^=yourcolor then 关键是要找的这样颜色虽然肉眼很容易区分,但是这个颜色集是蓝色和红色中的红色,不好界定啊,如果知道纯蓝色好红色,可以找出各种的红色吗
 
这个难度很大还是 了解下把 一般的是可以先用颜色做2个方向的投影 然后根据数据 分析出坐标 然后再在数据中获取到对象坐标,然后去轮廓腐蚀 然后 在判断。
 
从一幅图片中找出红色是很简单的,有很多种方法,最直接的就是扫描全像素(楼上说的)。但是把它标识出来,而且你要标识出来的形状是不固定的,这就很麻烦了,需要用到视觉识别。 如果你确定要用Delphi来做的话,网上有OpenCV1.0 for Delphi的库,我曾经用它实现过类似的功能,用起来也比较方便。只是版本旧了,但是做这个还是没问题的。
 
1.所谓的红色并不是单一的纯色,如何把肉眼界定的红色全都找出来??2.扫描全像素的话,找5、6个所谓的红色扫5、6遍,速度是个问题。
 
顶部