2014-12-07 23:07:49 +01:00
|
|
|
|
(*
|
|
|
|
|
**************************************************************************************************
|
|
|
|
|
Project Delphi-OpenCV
|
|
|
|
|
**************************************************************************************************
|
|
|
|
|
Contributor:
|
|
|
|
|
Laentir Valetov
|
|
|
|
|
email:laex@bk.ru
|
|
|
|
|
Mikhail Grigorev
|
|
|
|
|
email:sleuthound@gmail.com
|
|
|
|
|
**************************************************************************************************
|
|
|
|
|
You may retrieve the latest version of this file at the GitHub,
|
|
|
|
|
located at git://github.com/Laex/Delphi-OpenCV.git
|
|
|
|
|
**************************************************************************************************
|
|
|
|
|
License:
|
|
|
|
|
The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
|
|
|
|
|
you may not use this file except in compliance with the License. You may obtain a copy of the
|
|
|
|
|
License at http://www.mozilla.org/MPL/
|
|
|
|
|
|
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
|
|
|
|
ANY KIND, either express or implied. See the License for the specific language governing rights
|
|
|
|
|
and limitations under the License.
|
|
|
|
|
|
|
|
|
|
Alternatively, the contents of this file may be used under the terms of the
|
|
|
|
|
GNU Lesser General Public License (the "LGPL License"), in which case the
|
|
|
|
|
provisions of the LGPL License are applicable instead of those above.
|
|
|
|
|
If you wish to allow use of your version of this file only under the terms
|
|
|
|
|
of the LGPL License and not to allow others to use your version of this file
|
|
|
|
|
under the MPL, indicate your decision by deleting the provisions above and
|
|
|
|
|
replace them with the notice and other provisions required by the LGPL
|
|
|
|
|
License. If you do not delete the provisions above, a recipient may use
|
|
|
|
|
your version of this file under either the MPL or the LGPL License.
|
|
|
|
|
|
|
|
|
|
For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
|
|
|
|
|
**************************************************************************************************
|
|
|
|
|
Warning: Using Delphi XE2 syntax!
|
|
|
|
|
**************************************************************************************************
|
|
|
|
|
The Initial Developer of the Original Code:
|
|
|
|
|
OpenCV: open source computer vision library
|
|
|
|
|
Homepage: http://ocv.org
|
|
|
|
|
Online docs: http://docs.ocv.org
|
|
|
|
|
Q&A forum: http://answers.ocv.org
|
|
|
|
|
Dev zone: http://code.ocv.org
|
|
|
|
|
**************************************************************************************************
|
|
|
|
|
*)
|
|
|
|
|
|
2014-05-23 13:00:48 +02:00
|
|
|
|
{$I OpenCV.inc}
|
2014-09-29 09:12:47 +02:00
|
|
|
|
{$IFDEF DELPHI2009_UP}
|
2013-05-29 21:46:38 +02:00
|
|
|
|
{$POINTERMATH ON}
|
2014-05-23 13:00:48 +02:00
|
|
|
|
{$ENDIF}
|
2015-08-26 19:35:51 +02:00
|
|
|
|
unit ocv.utils;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
2014-05-22 08:53:48 +02:00
|
|
|
|
uses
|
2014-09-29 09:12:47 +02:00
|
|
|
|
{$IFDEF HAS_UNITSCOPE}
|
2014-10-18 01:12:32 +02:00
|
|
|
|
{$IFDEF MSWINDOWS}
|
2014-09-29 09:12:47 +02:00
|
|
|
|
Winapi.Windows,
|
2014-10-18 01:12:32 +02:00
|
|
|
|
{$ENDIF MSWINDOWS}
|
2014-05-22 08:53:48 +02:00
|
|
|
|
Vcl.Graphics,
|
2014-05-23 13:00:48 +02:00
|
|
|
|
{$ELSE}
|
2014-10-18 01:12:32 +02:00
|
|
|
|
{$IFDEF MSWINDOWS}
|
2014-05-23 13:00:48 +02:00
|
|
|
|
Windows,
|
2014-10-18 01:12:32 +02:00
|
|
|
|
{$ENDIF MSWINDOWS}
|
2014-05-23 13:00:48 +02:00
|
|
|
|
Graphics,
|
2014-09-29 09:12:47 +02:00
|
|
|
|
{$ENDIF HAS_UNITSCOPE}
|
2014-05-22 16:23:41 +02:00
|
|
|
|
ocv.core.types_c;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
|
|
|
|
|
Function hsv2rgb(hue: single): TCvScalar;
|
2014-08-24 22:37:55 +02:00
|
|
|
|
|
2014-10-18 01:12:32 +02:00
|
|
|
|
procedure IplImage2Bitmap(iplImg: PIplImage; var bitmap:
|
2014-12-07 23:07:49 +01:00
|
|
|
|
{$IFDEF DELPHIXE2_UP}Vcl.Graphics.TBitmap{$ELSE}Graphics.TBitmap{$ENDIF});
|
2014-09-29 09:12:47 +02:00
|
|
|
|
function cvImage2Bitmap(img: PIplImage): {$IFDEF DELPHIXE2_UP}Vcl.Graphics.TBitmap{$ELSE}Graphics.TBitmap{$ENDIF};
|
2013-08-10 08:40:36 +02:00
|
|
|
|
|
2013-09-15 14:02:26 +02:00
|
|
|
|
function ipDraw(dc: HDC; img: PIplImage; const rect: TRect; const Stretch: Boolean = true): Boolean; overload;
|
|
|
|
|
procedure ipDraw(const x, y: Integer; const _Grab: PIplImage; const Wnd: THandle); overload;
|
|
|
|
|
function CreateRGBBitmap(_Grab: PIplImage): HBITMAP;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
|
2013-06-13 16:10:58 +02:00
|
|
|
|
function c_str(const Text: String): pCVChar;
|
2013-06-10 06:21:02 +02:00
|
|
|
|
|
2013-09-25 21:18:23 +02:00
|
|
|
|
function ifthen(const Cond: Boolean; const ValueTrue, ValueFalse: pCvArr): pCvArr; overload;
|
|
|
|
|
function ifthen(const Cond: Boolean; const ValueTrue, ValueFalse: string): string; overload;
|
|
|
|
|
function ifthen(const Cond: Boolean; const ValueTrue, ValueFalse: TCvScalar): TCvScalar; overload;
|
|
|
|
|
|
2014-10-18 01:12:32 +02:00
|
|
|
|
function BitmapToIplImage(const bitmap:
|
2014-12-07 23:07:49 +01:00
|
|
|
|
{$IFDEF DELPHIXE2_UP}Vcl.Graphics.TBitmap{$ELSE}Graphics.TBitmap{$ENDIF}): PIplImage;
|
2014-05-15 02:09:58 +02:00
|
|
|
|
function CropIplImage(const src: PIplImage; const roi: TCvRect): PIplImage;
|
|
|
|
|
|
2014-12-08 22:19:11 +01:00
|
|
|
|
procedure ocvRGBToHSV(const R, G, B: byte; out _H, _S, _V: byte);
|
|
|
|
|
procedure ocvHSVToRGB(const _H, _S, _V: byte; out _R, _G, _B: byte);
|
2014-12-07 23:07:49 +01:00
|
|
|
|
|
2016-10-25 10:06:22 +02:00
|
|
|
|
{$IFDEF DELPHIXE3_UP}
|
2016-07-31 18:23:31 +02:00
|
|
|
|
Type
|
2016-10-25 10:06:22 +02:00
|
|
|
|
TStringAnsiHelper = record helper for String
|
2016-07-31 18:23:31 +02:00
|
|
|
|
function AsPAnsiChar: PAnsiChar;
|
|
|
|
|
end;
|
2016-10-25 10:06:22 +02:00
|
|
|
|
{$ENDIF}
|
2016-07-31 18:23:31 +02:00
|
|
|
|
|
2013-04-18 08:34:16 +02:00
|
|
|
|
implementation
|
|
|
|
|
|
2014-05-22 08:53:48 +02:00
|
|
|
|
uses
|
2014-09-29 09:12:47 +02:00
|
|
|
|
{$IFDEF HAS_UNITSCOPE}
|
2014-05-15 02:09:58 +02:00
|
|
|
|
System.SysUtils,
|
2014-05-23 13:00:48 +02:00
|
|
|
|
{$ELSE}
|
|
|
|
|
SysUtils,
|
2014-09-29 09:12:47 +02:00
|
|
|
|
{$ENDIF}
|
2014-12-07 23:07:49 +01:00
|
|
|
|
ocv.core_c, System.Math;
|
2014-05-15 02:09:58 +02:00
|
|
|
|
|
2016-10-25 10:06:22 +02:00
|
|
|
|
{$IFDEF DELPHIXE3_UP}
|
2016-07-31 18:23:31 +02:00
|
|
|
|
{ TStringAnsiHelper }
|
|
|
|
|
|
|
|
|
|
function TStringAnsiHelper.AsPAnsiChar: PAnsiChar;
|
|
|
|
|
begin
|
|
|
|
|
Result := c_str(Self);
|
|
|
|
|
end;
|
2016-10-25 10:06:22 +02:00
|
|
|
|
{$ENDIF}
|
2016-07-31 18:23:31 +02:00
|
|
|
|
|
2014-10-18 01:12:32 +02:00
|
|
|
|
function BitmapToIplImage(const bitmap:
|
2014-12-07 23:07:49 +01:00
|
|
|
|
{$IFDEF DELPHIXE2_UP}Vcl.Graphics.TBitmap{$ELSE}Graphics.TBitmap{$ENDIF}): PIplImage;
|
2014-05-15 02:09:58 +02:00
|
|
|
|
Var
|
2014-08-24 22:37:55 +02:00
|
|
|
|
BMI: BITMAPINFO;
|
2014-05-15 02:09:58 +02:00
|
|
|
|
begin
|
|
|
|
|
Assert(bitmap.PixelFormat = pf24bit); // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2014-08-24 22:37:55 +02:00
|
|
|
|
ZeroMemory(@BMI, sizeof(BMI));
|
|
|
|
|
BMI.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
|
|
|
|
|
BMI.bmiHeader.biWidth := bitmap.Width;
|
|
|
|
|
BMI.bmiHeader.biHeight := -bitmap.Height;
|
|
|
|
|
BMI.bmiHeader.biPlanes := 1;
|
|
|
|
|
BMI.bmiHeader.biBitCount := 24; // only 24-bit
|
|
|
|
|
BMI.bmiHeader.biCompression := BI_RGB;
|
|
|
|
|
Result := cvCreateImage(cvSize(bitmap.Width, bitmap.Height), IPL_DEPTH_8U, 3); // only 24-bit
|
|
|
|
|
GetDIBits(bitmap.Canvas.Handle, bitmap.Handle, 0, bitmap.Height, Result^.ImageData, BMI, DIB_RGB_COLORS);
|
2014-05-15 02:09:58 +02:00
|
|
|
|
end;
|
|
|
|
|
|
2014-09-29 09:12:47 +02:00
|
|
|
|
// function BitmapToIplImage(const bitmap: {$IFDEF DELPHIXE2_UP}Vcl.Graphics.TBitmap{$ELSE}Graphics.TBitmap{$ENDIF}): PIplImage;
|
2014-08-24 22:37:55 +02:00
|
|
|
|
// Var
|
|
|
|
|
// bitmapData: PByte;
|
|
|
|
|
// begin
|
|
|
|
|
// Assert(bitmap.PixelFormat = pf24bit); // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// bitmapData := bitmap.Scanline[0];
|
|
|
|
|
// Result := cvCreateImage(cvSize(bitmap.Width, bitmap.Height), IPL_DEPTH_8U, 3);
|
|
|
|
|
// CopyMemory(Result^.imageData, bitmapData, Result^.imageSize);
|
|
|
|
|
// Result^.imageDataOrigin := nil;
|
|
|
|
|
// Result^.imageId := nil;
|
|
|
|
|
// Result^.maskROI := nil;
|
|
|
|
|
// Result^.roi := nil;
|
|
|
|
|
// end;
|
|
|
|
|
|
2014-05-15 02:09:58 +02:00
|
|
|
|
function CropIplImage(const src: PIplImage; const roi: TCvRect): PIplImage;
|
|
|
|
|
begin
|
|
|
|
|
// Must have dimensions of output image
|
|
|
|
|
Result := cvCreateImage(cvSize(roi.Width, roi.Height), src^.depth, src^.nChannels);
|
|
|
|
|
// Say what the source region is
|
|
|
|
|
cvSetImageROI(src, roi);
|
|
|
|
|
// Do the copy
|
|
|
|
|
cvCopyImage(src, Result);
|
|
|
|
|
cvResetImageROI(src);
|
|
|
|
|
end;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
|
2013-09-25 21:18:23 +02:00
|
|
|
|
function ifthen(const Cond: Boolean; const ValueTrue, ValueFalse: pCvArr): pCvArr; overload;
|
|
|
|
|
begin
|
|
|
|
|
if Cond then
|
|
|
|
|
Result := ValueTrue
|
|
|
|
|
else
|
|
|
|
|
Result := ValueFalse;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function ifthen(const Cond: Boolean; const ValueTrue, ValueFalse: string): string; overload;
|
|
|
|
|
begin
|
|
|
|
|
if Cond then
|
|
|
|
|
Result := ValueTrue
|
|
|
|
|
else
|
|
|
|
|
Result := ValueFalse;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function ifthen(const Cond: Boolean; const ValueTrue, ValueFalse: TCvScalar): TCvScalar; overload;
|
|
|
|
|
begin
|
|
|
|
|
if Cond then
|
|
|
|
|
Result := ValueTrue
|
|
|
|
|
else
|
|
|
|
|
Result := ValueFalse;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-09-15 14:02:26 +02:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> API <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> RGB <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
function CreateRGBBitmap(_Grab: PIplImage): HBITMAP;
|
|
|
|
|
|
2014-08-27 06:37:44 +02:00
|
|
|
|
function WIDTHBYTES(bits: DWORD): DWORD; {$IFDEF USE_INLINE}inline; {$ENDIF}
|
2013-09-15 14:02:26 +02:00
|
|
|
|
begin
|
2014-05-08 22:52:42 +02:00
|
|
|
|
Result := ((((bits) + 31) div 32) * 4);
|
2013-09-15 14:02:26 +02:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Var
|
2014-05-08 22:52:42 +02:00
|
|
|
|
lpbi: TBitmapInfo;
|
2014-05-15 02:09:58 +02:00
|
|
|
|
App: PByte;
|
2013-09-15 14:02:26 +02:00
|
|
|
|
pBits: Pointer;
|
2014-05-08 22:52:42 +02:00
|
|
|
|
i, j: Integer;
|
2013-09-15 14:02:26 +02:00
|
|
|
|
begin
|
2014-08-24 22:37:55 +02:00
|
|
|
|
lpbi.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
|
2014-05-15 02:09:58 +02:00
|
|
|
|
lpbi.bmiHeader.biWidth := _Grab^.Width;
|
|
|
|
|
lpbi.bmiHeader.biHeight := _Grab^.Height;
|
2014-05-08 22:52:42 +02:00
|
|
|
|
lpbi.bmiHeader.biPlanes := 1;
|
|
|
|
|
lpbi.bmiHeader.biBitCount := 24;
|
|
|
|
|
lpbi.bmiHeader.biCompression := BI_RGB;
|
2014-05-15 02:09:58 +02:00
|
|
|
|
lpbi.bmiHeader.biSizeImage := WIDTHBYTES(_Grab^.Width * 8) * _Grab^.Height;
|
2013-09-15 14:02:26 +02:00
|
|
|
|
lpbi.bmiHeader.biXPelsPerMeter := 0;
|
|
|
|
|
lpbi.bmiHeader.biYPelsPerMeter := 0;
|
2014-05-08 22:52:42 +02:00
|
|
|
|
lpbi.bmiHeader.biClrUsed := 0;
|
|
|
|
|
lpbi.bmiHeader.biClrImportant := 0;
|
|
|
|
|
Result := CreateDIBSection(0, lpbi, DIB_RGB_COLORS, pBits, 0, 0);
|
|
|
|
|
if Result <> 0 then
|
2013-09-15 14:02:26 +02:00
|
|
|
|
begin
|
|
|
|
|
App := pBits;
|
|
|
|
|
|
|
|
|
|
if (_Grab^.nChannels = 1) then // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
begin
|
|
|
|
|
|
2014-05-15 02:09:58 +02:00
|
|
|
|
for i := 0 to _Grab^.Height - 1 do
|
2013-09-15 14:02:26 +02:00
|
|
|
|
begin
|
2014-05-15 02:09:58 +02:00
|
|
|
|
for j := 0 to _Grab^.Width - 1 do
|
2013-09-15 14:02:26 +02:00
|
|
|
|
begin
|
2014-08-24 22:37:55 +02:00
|
|
|
|
App[_Grab^.Width * 3 * (_Grab^.Height - i - 1) + j * 3] := PByte(_Grab^.ImageData)[_Grab^.Width * (i) + j];
|
2016-07-31 18:23:31 +02:00
|
|
|
|
App[_Grab^.Width * 3 * (_Grab^.Height - i - 1) + j * 3 + 1] := PByte(_Grab^.ImageData)[_Grab^.Width * (i) + j];
|
|
|
|
|
App[_Grab^.Width * 3 * (_Grab^.Height - i - 1) + j * 3 + 2] := PByte(_Grab^.ImageData)[_Grab^.Width * (i) + j];
|
2013-09-15 14:02:26 +02:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
if (_Grab^.nChannels = 3) then // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
begin
|
2014-05-15 02:09:58 +02:00
|
|
|
|
for i := 0 to _Grab^.Height - 1 do
|
2013-09-15 14:02:26 +02:00
|
|
|
|
begin
|
2016-07-31 18:23:31 +02:00
|
|
|
|
CopyMemory(App + _Grab^.Width * 3 * (_Grab^.Height - i - 1), PByte(_Grab^.ImageData) + _Grab^.Width * 3 * i, _Grab^.Width * 3);
|
2013-09-15 14:02:26 +02:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> HANDLE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
procedure ipDraw(const x, y: Integer; const _Grab: PIplImage; const Wnd: THandle); overload;
|
|
|
|
|
Var
|
|
|
|
|
hMemDC, dc: HDC;
|
2014-05-08 22:52:42 +02:00
|
|
|
|
bitmap: HBITMAP;
|
2013-09-15 14:02:26 +02:00
|
|
|
|
begin
|
2014-05-08 22:52:42 +02:00
|
|
|
|
dc := GetDC(Wnd);
|
2013-09-15 14:02:26 +02:00
|
|
|
|
hMemDC := CreateCompatibleDC(dc);
|
|
|
|
|
bitmap := CreateRGBBitmap(_Grab);
|
2014-05-08 22:52:42 +02:00
|
|
|
|
SelectObject(hMemDC, bitmap);
|
2014-05-15 02:09:58 +02:00
|
|
|
|
BitBlt(dc, x, y, _Grab^.Width, _Grab^.Height, hMemDC, 0, 0, SRCCOPY);
|
2013-09-15 14:02:26 +02:00
|
|
|
|
DeleteObject(bitmap);
|
|
|
|
|
DeleteDC(hMemDC);
|
|
|
|
|
DeleteDC(dc);
|
|
|
|
|
end;
|
|
|
|
|
|
2013-06-13 16:10:58 +02:00
|
|
|
|
function c_str(const Text: String): pCVChar;
|
|
|
|
|
begin
|
2014-05-08 22:52:42 +02:00
|
|
|
|
Result := pCVChar(@(AnsiString(Text)[1]));
|
2013-06-13 16:10:58 +02:00
|
|
|
|
end;
|
|
|
|
|
|
2013-04-18 08:34:16 +02:00
|
|
|
|
Function hsv2rgb(hue: single): TCvScalar;
|
|
|
|
|
var
|
2014-05-08 22:52:42 +02:00
|
|
|
|
rgb: array [0 .. 2] of Integer;
|
2013-05-21 01:35:54 +02:00
|
|
|
|
p, sector: Integer;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
const
|
2013-05-21 01:35:54 +02:00
|
|
|
|
sector_data: array [0 .. 5, 0 .. 2] of Integer = ((0, 2, 1), (1, 2, 0), (1, 0, 2), (2, 0, 1), (2, 1, 0), (0, 1, 2));
|
2013-04-18 08:34:16 +02:00
|
|
|
|
Begin
|
2014-05-08 22:52:42 +02:00
|
|
|
|
hue := hue * 0.033333333333333333333333333333333;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
sector := cvFloor(hue);
|
2014-08-06 00:36:22 +02:00
|
|
|
|
// p := cvRound(255 * (hue - sector));
|
2013-04-18 08:34:16 +02:00
|
|
|
|
if (sector and 1) = 1 then
|
|
|
|
|
p := 255
|
|
|
|
|
else
|
|
|
|
|
p := 0;
|
|
|
|
|
|
|
|
|
|
rgb[sector_data[sector][0]] := 255;
|
|
|
|
|
rgb[sector_data[sector][1]] := 0;
|
|
|
|
|
rgb[sector_data[sector][2]] := p;
|
|
|
|
|
|
2014-05-08 22:52:42 +02:00
|
|
|
|
Result := cvScalar(rgb[2], rgb[1], rgb[0], 0);
|
2013-04-18 08:34:16 +02:00
|
|
|
|
End;
|
|
|
|
|
|
2014-08-06 00:36:22 +02:00
|
|
|
|
{ -----------------------------------------------------------------------------
|
2013-04-18 08:34:16 +02:00
|
|
|
|
Procedure: IplImage2Bitmap
|
|
|
|
|
Author: De Sanctis
|
|
|
|
|
Date: 23-set-2005
|
|
|
|
|
Arguments: iplImg: PIplImage; bitmap: TBitmap
|
|
|
|
|
Description: convert a IplImage to a Windows bitmap
|
2014-08-06 00:36:22 +02:00
|
|
|
|
----------------------------------------------------------------------------- }
|
2014-10-18 01:12:32 +02:00
|
|
|
|
procedure IplImage2Bitmap(iplImg: PIplImage; var bitmap:
|
2014-12-07 23:07:49 +01:00
|
|
|
|
{$IFDEF DELPHIXE2_UP}Vcl.Graphics.TBitmap{$ELSE}Graphics.TBitmap{$ENDIF});
|
2013-04-18 08:34:16 +02:00
|
|
|
|
VAR
|
2014-05-08 22:52:42 +02:00
|
|
|
|
i, j: Integer;
|
|
|
|
|
offset: longint;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
dataByte, RowIn: PByteArray;
|
2014-05-15 02:09:58 +02:00
|
|
|
|
// channelsCount: Integer;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
BEGIN
|
|
|
|
|
TRY
|
|
|
|
|
// assert((iplImg.Depth = 8) and (iplImg.NChannels = 3),
|
|
|
|
|
// 'IplImage2Bitmap: Not a 24 bit color iplImage!');
|
2014-05-15 02:09:58 +02:00
|
|
|
|
bitmap.Height := iplImg.Height;
|
|
|
|
|
bitmap.Width := iplImg.Width;
|
|
|
|
|
FOR j := 0 TO bitmap.Height - 1 DO
|
2013-04-18 08:34:16 +02:00
|
|
|
|
BEGIN
|
|
|
|
|
// origin BL = Bottom-Left
|
|
|
|
|
if (iplImg.Origin = IPL_ORIGIN_BL) then
|
2014-05-15 02:09:58 +02:00
|
|
|
|
RowIn := bitmap.Scanline[bitmap.Height - 1 - j]
|
2013-04-18 08:34:16 +02:00
|
|
|
|
else
|
|
|
|
|
RowIn := bitmap.Scanline[j];
|
|
|
|
|
|
2014-08-24 22:37:55 +02:00
|
|
|
|
offset := longint(iplImg.ImageData) + iplImg.WidthStep * j;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
dataByte := PByteArray(offset);
|
|
|
|
|
|
|
|
|
|
if (iplImg.ChannelSeq = 'BGR') then
|
|
|
|
|
begin
|
2014-08-06 00:36:22 +02:00
|
|
|
|
{ direct copy of the iplImage row bytes to bitmap row }
|
2014-05-08 22:52:42 +02:00
|
|
|
|
CopyMemory(RowIn, dataByte, iplImg.WidthStep);
|
2013-04-18 08:34:16 +02:00
|
|
|
|
End
|
|
|
|
|
else if (iplImg.ChannelSeq = 'GRAY') then
|
2014-05-15 02:09:58 +02:00
|
|
|
|
FOR i := 0 TO bitmap.Width - 1 DO
|
2013-04-18 08:34:16 +02:00
|
|
|
|
begin
|
2014-05-08 22:52:42 +02:00
|
|
|
|
RowIn[3 * i] := dataByte[i];
|
2013-04-18 08:34:16 +02:00
|
|
|
|
RowIn[3 * i + 1] := dataByte[i];
|
|
|
|
|
RowIn[3 * i + 2] := dataByte[i];
|
|
|
|
|
End
|
|
|
|
|
else
|
2014-05-15 02:09:58 +02:00
|
|
|
|
FOR i := 0 TO 3 * bitmap.Width - 1 DO
|
2013-04-18 08:34:16 +02:00
|
|
|
|
begin
|
2014-05-08 22:52:42 +02:00
|
|
|
|
RowIn[i] := dataByte[i + 2];
|
2013-04-18 08:34:16 +02:00
|
|
|
|
RowIn[i + 1] := dataByte[i + 1];
|
|
|
|
|
RowIn[i + 2] := dataByte[i];
|
|
|
|
|
End;
|
|
|
|
|
End;
|
|
|
|
|
Except
|
|
|
|
|
End
|
2014-08-06 00:36:22 +02:00
|
|
|
|
END; { IplImage2Bitmap }
|
2013-04-18 08:34:16 +02:00
|
|
|
|
|
2014-09-29 09:12:47 +02:00
|
|
|
|
function cvImage2Bitmap(img: PIplImage): {$IFDEF DELPHIXE2_UP}Vcl.Graphics.TBitmap{$ELSE}Graphics.TBitmap{$ENDIF};
|
2013-04-18 08:34:16 +02:00
|
|
|
|
var
|
2014-05-15 02:09:58 +02:00
|
|
|
|
// info: string;
|
2014-09-29 09:12:47 +02:00
|
|
|
|
bmp: {$IFDEF DELPHIXE2_UP}Vcl.Graphics.TBitmap{$ELSE}Graphics.TBitmap{$ENDIF};
|
2014-05-08 22:52:42 +02:00
|
|
|
|
deep: Integer;
|
2013-05-21 01:35:54 +02:00
|
|
|
|
i, j, K, wStep, Channels: Integer;
|
2014-05-08 22:52:42 +02:00
|
|
|
|
data: PByteArray;
|
|
|
|
|
pb: PByteArray;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
begin
|
2014-05-08 22:52:42 +02:00
|
|
|
|
Result := NIL;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
if (img <> NIL) then
|
|
|
|
|
begin
|
2014-09-29 09:12:47 +02:00
|
|
|
|
bmp := {$IFDEF DELPHIXE2_UP}Vcl.Graphics.TBitmap.Create{$ELSE}Graphics.TBitmap.Create{$ENDIF};
|
2014-05-15 02:09:58 +02:00
|
|
|
|
bmp.Width := img^.Width;
|
|
|
|
|
bmp.Height := img^.Height;
|
2014-05-08 22:52:42 +02:00
|
|
|
|
deep := img^.nChannels * img^.depth;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
case deep of
|
|
|
|
|
8:
|
|
|
|
|
bmp.PixelFormat := pf8bit;
|
|
|
|
|
16:
|
|
|
|
|
bmp.PixelFormat := pf16bit;
|
|
|
|
|
24:
|
|
|
|
|
bmp.PixelFormat := pf24bit;
|
|
|
|
|
32:
|
|
|
|
|
bmp.PixelFormat := pf32bit;
|
|
|
|
|
End;
|
2014-05-08 22:52:42 +02:00
|
|
|
|
wStep := img^.WidthStep;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
Channels := img^.nChannels;
|
2014-08-24 22:37:55 +02:00
|
|
|
|
data := Pointer(img^.ImageData);
|
2014-05-15 02:09:58 +02:00
|
|
|
|
for i := 0 to img^.Height - 1 do
|
2013-04-18 08:34:16 +02:00
|
|
|
|
begin
|
2014-05-08 22:52:42 +02:00
|
|
|
|
pb := bmp.Scanline[i];
|
2014-05-15 02:09:58 +02:00
|
|
|
|
for j := 0 to img^.Width - 1 do
|
2013-04-18 08:34:16 +02:00
|
|
|
|
begin
|
2014-05-08 22:52:42 +02:00
|
|
|
|
for K := 0 to Channels - 1 do
|
2013-04-18 08:34:16 +02:00
|
|
|
|
pb[3 * j + K] := data[i * wStep + j * Channels + K]
|
|
|
|
|
End;
|
|
|
|
|
End;
|
2014-05-08 22:52:42 +02:00
|
|
|
|
Result := bmp;
|
2013-04-18 08:34:16 +02:00
|
|
|
|
// bmp.Free;
|
|
|
|
|
End;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-09-15 14:02:26 +02:00
|
|
|
|
function ipDraw(dc: HDC; img: PIplImage; const rect: TRect; const Stretch: Boolean = true): Boolean;
|
2013-05-29 21:46:38 +02:00
|
|
|
|
|
|
|
|
|
Type
|
2014-12-07 23:07:49 +01:00
|
|
|
|
pCOLORREF = ^COLORREF;
|
2013-05-29 21:46:38 +02:00
|
|
|
|
pBITMAPINFOHEADER = ^BITMAPINFOHEADER;
|
|
|
|
|
|
|
|
|
|
Var
|
2014-05-08 22:52:42 +02:00
|
|
|
|
isrgb: Boolean;
|
|
|
|
|
isgray: Boolean;
|
2014-08-24 22:37:55 +02:00
|
|
|
|
buf: array [1 .. sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256] of byte;
|
2014-05-08 22:52:42 +02:00
|
|
|
|
dibhdr: pBITMAPINFOHEADER;
|
2013-05-29 21:46:38 +02:00
|
|
|
|
_dibhdr: TBitmapInfo ABSOLUTE buf;
|
2014-05-08 22:52:42 +02:00
|
|
|
|
_rgb: pCOLORREF;
|
|
|
|
|
i: Integer;
|
2014-05-20 17:20:29 +02:00
|
|
|
|
iResult: Integer;
|
2013-05-29 21:46:38 +02:00
|
|
|
|
begin
|
2014-08-24 22:37:55 +02:00
|
|
|
|
if (not Assigned(img)) or (not Assigned(img^.ImageData)) then
|
2013-05-29 21:46:38 +02:00
|
|
|
|
Exit(false);
|
2014-05-20 17:20:29 +02:00
|
|
|
|
|
2016-07-31 18:23:31 +02:00
|
|
|
|
isrgb := ('R' = upcase(img^.colorModel[0])) and ('G' = upcase(img^.colorModel[1])) and ('B' = upcase(img^.colorModel[2]));
|
2013-05-29 21:46:38 +02:00
|
|
|
|
isgray := 'G' = upcase(img^.colorModel[0]);
|
2014-05-20 17:20:29 +02:00
|
|
|
|
|
2013-05-29 21:46:38 +02:00
|
|
|
|
if (not isgray) and (not isrgb) then
|
|
|
|
|
Exit(false);
|
|
|
|
|
if (1 = img^.nChannels) and (not isgray) then
|
|
|
|
|
Exit(false);
|
|
|
|
|
|
|
|
|
|
dibhdr := @buf;
|
2014-08-24 22:37:55 +02:00
|
|
|
|
_rgb := pCOLORREF(Integer(dibhdr) + sizeof(BITMAPINFOHEADER));
|
2013-05-29 21:46:38 +02:00
|
|
|
|
|
|
|
|
|
if (isgray) then
|
2014-05-08 22:52:42 +02:00
|
|
|
|
for i := 0 to 255 do
|
|
|
|
|
_rgb[i] := rgb(i, i, i);
|
2014-05-20 17:20:29 +02:00
|
|
|
|
|
2014-08-24 22:37:55 +02:00
|
|
|
|
dibhdr^.biSize := sizeof(BITMAPINFOHEADER);
|
2014-05-15 02:09:58 +02:00
|
|
|
|
dibhdr^.biWidth := img^.Width;
|
2013-05-29 21:46:38 +02:00
|
|
|
|
// Check origin for display
|
|
|
|
|
if img^.Origin = 0 then
|
2014-05-15 02:09:58 +02:00
|
|
|
|
dibhdr^.biHeight := -img^.Height
|
2013-05-29 21:46:38 +02:00
|
|
|
|
else
|
2014-05-15 02:09:58 +02:00
|
|
|
|
dibhdr^.biHeight := img^.Height;
|
2013-05-29 21:46:38 +02:00
|
|
|
|
|
2014-05-08 22:52:42 +02:00
|
|
|
|
dibhdr^.biPlanes := 1;
|
|
|
|
|
dibhdr^.biBitCount := 8 * img^.nChannels;
|
|
|
|
|
dibhdr^.biCompression := BI_RGB;
|
|
|
|
|
dibhdr^.biSizeImage := 0; // img^.imageSize;
|
2013-05-29 21:46:38 +02:00
|
|
|
|
dibhdr^.biXPelsPerMeter := 0;
|
|
|
|
|
dibhdr^.biYPelsPerMeter := 0;
|
2014-05-08 22:52:42 +02:00
|
|
|
|
dibhdr^.biClrUsed := 0;
|
|
|
|
|
dibhdr^.biClrImportant := 0;
|
2013-05-29 21:46:38 +02:00
|
|
|
|
|
|
|
|
|
if Stretch then
|
|
|
|
|
begin
|
2014-05-08 22:52:42 +02:00
|
|
|
|
SetStretchBltMode(dc, COLORONCOLOR);
|
2014-05-20 17:20:29 +02:00
|
|
|
|
SetMapMode(dc, MM_TEXT);
|
2013-05-29 21:46:38 +02:00
|
|
|
|
// Stretch the image to fit the rectangle
|
2014-10-18 01:12:32 +02:00
|
|
|
|
iResult := StretchDIBits(dc, rect.left, rect.top,
|
2014-12-07 23:07:49 +01:00
|
|
|
|
{$IFDEF DELPHIXE2_UP}rect.Width{$ELSE}rect.Right - rect.left{$ENDIF},
|
2016-07-31 18:23:31 +02:00
|
|
|
|
{$IFDEF DELPHIXE2_UP}rect.Height{$ELSE}rect.Bottom - rect.top{$ENDIF}, 0, 0, img^.Width, img^.Height, img^.ImageData, _dibhdr,
|
|
|
|
|
DIB_RGB_COLORS, SRCCOPY);
|
2014-08-06 00:36:22 +02:00
|
|
|
|
Result := (iResult > 0); // and (iResult <> GDI_ERROR);
|
2013-05-29 21:46:38 +02:00
|
|
|
|
end
|
|
|
|
|
else
|
2014-05-20 17:20:29 +02:00
|
|
|
|
begin
|
2013-05-29 21:46:38 +02:00
|
|
|
|
// Draw without scaling
|
2016-07-31 18:23:31 +02:00
|
|
|
|
iResult := SetDIBitsToDevice(dc, rect.left, rect.top, img^.Width, img^.Height, 0, 0, 0, img^.Height, img^.ImageData, _dibhdr, DIB_RGB_COLORS);
|
2014-08-06 00:36:22 +02:00
|
|
|
|
Result := (iResult > 0); // and (iResult <> GDI_ERROR);
|
2014-05-20 17:20:29 +02:00
|
|
|
|
end;
|
2013-05-29 21:46:38 +02:00
|
|
|
|
end;
|
|
|
|
|
|
2014-12-08 22:19:11 +01:00
|
|
|
|
procedure ocvHSVToRGB(const _H, _S, _V: byte; out _R, _G, _B: byte);
|
2014-12-07 23:07:49 +01:00
|
|
|
|
{
|
|
|
|
|
in
|
|
|
|
|
H = Hue. Range is from 0..180. or H < 0 for gray
|
|
|
|
|
S = Satration. Range is 0..255 where 0 is white and 255 is no saturation.
|
|
|
|
|
V = Value. Range is 0..255
|
|
|
|
|
|
|
|
|
|
out
|
|
|
|
|
R = 0..255
|
|
|
|
|
G = 0..255
|
|
|
|
|
B = 0..255
|
|
|
|
|
|
|
|
|
|
If H < 0 then the result is a gray value R=V, G=V, B=V
|
|
|
|
|
}
|
|
|
|
|
const
|
|
|
|
|
SectionSize = 60 / 360;
|
|
|
|
|
var
|
|
|
|
|
Section: single;
|
|
|
|
|
SectionIndex: Integer;
|
|
|
|
|
F: single;
|
|
|
|
|
p, q, t: single;
|
2014-12-08 22:19:11 +01:00
|
|
|
|
H, S: single;
|
2014-12-07 23:07:49 +01:00
|
|
|
|
begin
|
2014-12-08 22:19:11 +01:00
|
|
|
|
H := _H / 180;
|
|
|
|
|
S := _S / 255;
|
2014-12-07 23:07:49 +01:00
|
|
|
|
|
|
|
|
|
if H < 0 then
|
|
|
|
|
begin
|
2014-12-08 22:19:11 +01:00
|
|
|
|
_R := _V;
|
|
|
|
|
_G := _R;
|
|
|
|
|
_B := _R;
|
2014-12-07 23:07:49 +01:00
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
Section := H / SectionSize;
|
|
|
|
|
SectionIndex := Floor(Section);
|
|
|
|
|
F := Section - SectionIndex;
|
2014-12-08 22:19:11 +01:00
|
|
|
|
p := _V * (1 - S);
|
|
|
|
|
q := _V * (1 - S * F);
|
|
|
|
|
t := _V * (1 - S * (1 - F));
|
2014-12-07 23:07:49 +01:00
|
|
|
|
case SectionIndex of
|
|
|
|
|
0:
|
|
|
|
|
begin
|
2014-12-08 22:19:11 +01:00
|
|
|
|
_R := _V;
|
|
|
|
|
_G := Trunc(t);
|
|
|
|
|
_B := Trunc(p);
|
2014-12-07 23:07:49 +01:00
|
|
|
|
end;
|
|
|
|
|
1:
|
|
|
|
|
begin
|
2014-12-08 22:19:11 +01:00
|
|
|
|
_R := Trunc(q);
|
|
|
|
|
_G := _V;
|
|
|
|
|
_B := Trunc(p);
|
2014-12-07 23:07:49 +01:00
|
|
|
|
end;
|
|
|
|
|
2:
|
|
|
|
|
begin
|
2014-12-08 22:19:11 +01:00
|
|
|
|
_R := Trunc(p);
|
|
|
|
|
_G := _V;
|
|
|
|
|
_B := Trunc(t);
|
2014-12-07 23:07:49 +01:00
|
|
|
|
end;
|
|
|
|
|
3:
|
|
|
|
|
begin
|
2014-12-08 22:19:11 +01:00
|
|
|
|
_R := Trunc(p);
|
|
|
|
|
_G := Trunc(q);
|
|
|
|
|
_B := _V;
|
2014-12-07 23:07:49 +01:00
|
|
|
|
end;
|
|
|
|
|
4:
|
|
|
|
|
begin
|
2014-12-08 22:19:11 +01:00
|
|
|
|
_R := Trunc(t);
|
|
|
|
|
_G := Trunc(p);
|
|
|
|
|
_B := _V;
|
2014-12-07 23:07:49 +01:00
|
|
|
|
end;
|
|
|
|
|
else
|
2014-12-08 22:19:11 +01:00
|
|
|
|
_R := _V;
|
|
|
|
|
_G := Trunc(p);
|
|
|
|
|
_B := Trunc(q);
|
2014-12-07 23:07:49 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2014-12-08 22:19:11 +01:00
|
|
|
|
procedure ocvRGBToHSV(const R, G, B: byte; out _H, _S, _V: byte);
|
2014-12-07 23:07:49 +01:00
|
|
|
|
{
|
|
|
|
|
in
|
|
|
|
|
R = 0..255
|
|
|
|
|
G = 0..255
|
|
|
|
|
B = 0..255
|
|
|
|
|
|
|
|
|
|
out
|
|
|
|
|
H = Hue. -1 for grey scale or range 0..180. 0..180 represents 0..360 degrees
|
|
|
|
|
S = Saturation. Range = 0..255. 0 = white, 255 = no saturation.
|
|
|
|
|
V = Value or intensity. Range 0..255
|
|
|
|
|
}
|
|
|
|
|
var
|
|
|
|
|
rgb: array [0 .. 2] of single;
|
|
|
|
|
MinIndex, MaxIndex: Integer;
|
|
|
|
|
Range: single;
|
2014-12-08 22:19:11 +01:00
|
|
|
|
H, S, V: single;
|
2014-12-07 23:07:49 +01:00
|
|
|
|
begin
|
|
|
|
|
rgb[0] := R;
|
|
|
|
|
rgb[1] := G;
|
|
|
|
|
rgb[2] := B;
|
|
|
|
|
|
|
|
|
|
MinIndex := 0;
|
|
|
|
|
if G < R then
|
|
|
|
|
MinIndex := 1;
|
|
|
|
|
|
|
|
|
|
if B < rgb[MinIndex] then
|
|
|
|
|
MinIndex := 2;
|
|
|
|
|
|
|
|
|
|
MaxIndex := 0;
|
|
|
|
|
if G > R then
|
|
|
|
|
MaxIndex := 1;
|
|
|
|
|
|
|
|
|
|
if B > rgb[MaxIndex] then
|
|
|
|
|
MaxIndex := 2;
|
|
|
|
|
|
|
|
|
|
Range := rgb[MaxIndex] - rgb[MinIndex];
|
|
|
|
|
|
|
|
|
|
// Check for a gray level
|
|
|
|
|
if Range = 0 then
|
|
|
|
|
begin
|
2014-12-08 22:19:11 +01:00
|
|
|
|
_H := 0; // Can't determine on greys, so set to -1
|
|
|
|
|
_S := 0; // Gray is at the center;
|
|
|
|
|
_V := R; // could choose R, G, or B because they are all the same value.
|
2014-12-07 23:07:49 +01:00
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
case MaxIndex of
|
|
|
|
|
0:
|
|
|
|
|
H := (G - B) / Range;
|
|
|
|
|
1:
|
|
|
|
|
H := 2 + (B - R) / Range;
|
|
|
|
|
2:
|
|
|
|
|
H := 4 + (R - G) / Range;
|
2016-07-31 18:23:31 +02:00
|
|
|
|
else
|
|
|
|
|
H := 0;
|
2014-12-07 23:07:49 +01:00
|
|
|
|
end;
|
|
|
|
|
S := Range / rgb[MaxIndex];
|
|
|
|
|
V := rgb[MaxIndex];
|
|
|
|
|
H := H * (1 / 6);
|
|
|
|
|
if H < 0 then
|
|
|
|
|
H := 1 + H;
|
|
|
|
|
|
2014-12-08 22:19:11 +01:00
|
|
|
|
_H := Trunc(H * 180);
|
|
|
|
|
_S := Trunc(S * 255);
|
|
|
|
|
_V := Trunc(V);
|
2014-12-07 23:07:49 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-04-18 08:34:16 +02:00
|
|
|
|
end.
|