極座標変換

Classes

ClassDescription
Public classCFviPolarTrans
極座標変換クラス
Public classCFviPolarTransParam
極座標変換パラメータ構造クラス
Public classErrorCode
エラーコード(極座標変換関連)
Public classFunction
極座標変換関連関数群

Enumerations

EnumerationDescription
Public enumerationCoordinateMode
基準座標モード
Public enumerationSamplingMode
濃度補間方法

Remarks

極座標変換関連のクラス、関数、定数等を局所化するネームスペースです。


トピック:


解説:

本ライブラリでの極座標とは、2次元ユークリッド空間での極座標であり、 円座標(Circular Polar Coordinate)です。
下図に座標系を示します。



変換式は、以下の通りです。





構成:

この機能は、極座標変換を行う本体のクラスと関数、極座標変換パラメータを保有するデータ構造クラスで構成されます。 関数は、FVIL.PolarTrans.Function クラスに集約しています。

  • 本体(クラス):
    クラス内容
    CFviPolarTrans画像の極座標変換(または逆変換)を行うクラスです。
  • 関数:
    関数内容
    Transform画像の極座標変換(または逆変換)を行う関数です。上記のクラスをラッピングしたものです。
    Transform点列の極座標変換(または逆変換)を行う関数です。
  • データ構造:
    クラスデータID内容
    CFviPolarTransParam1700極座標変換(または逆変換)を行う際に使用するパラメータです。

[↑戻る]


極座標変換と逆変換:

本ライブラリでは矩形から円形への変換を極座標変換と定義します。
下図の左から右への変換が極座標変換、右から左が逆変換です。 変換方向は、
CFviPolarTrans クラスの Invert プロパティで設定できます。

[↑戻る]


極座標変換パラメータ:

極座標変換パラメータは、CFviPolarTransParam に集約しています。 詳細については、このクラスの説明をご参照ください。

[↑戻る]


基準座標モード:

基準座標モードは、処理対象の領域(矩形)のどの位置を基準位置とするかを示します。 CoordinateMode 定数に定義された以下の4種類から指定することができます。

  • Left ... 矩形の左辺が回転方向です。左上角と円中心、上辺と円半径が対応します。
  • Right ... 矩形の右辺が回転方向です。右下角と円中心、下辺と円半径が対応します。
  • Upper ... 矩形の上辺が回転方向です。右上角と円中心、右辺と円半径が対応します。
  • Lower ... 矩形の下辺が回転方向です。左下角と円中心、左辺と円半径が対応します。

基準座標モードによって、処理対象領域(矩形)と出力領域(円形)を示すパラメータの対応関係が変化します。 詳細については、CFviPolarTransParam の説明をご参照ください。

下図に基準座標モードの指定例を示します。

  • 橙色枠 ... 処理対象領域(矩形)を示します。
  • 緑色×印 ... 処理対象領域(矩形)の基準位置を示します。出力領域(円形)の中心に対応します。
  • 赤色線 ... 出力領域の回転開始角を示します。

下図は、上図左の処理対象領域(矩形)を極座標変換した例を示します。 基準座標モードは、FVIL.PolarTrans.CoordinateMode.Left を選択しているものとします。

  1. 基準となる例です。回転開始角を 0°、回転範囲を 360°、処理対象領域(矩形)の幅と高さを 100,300 と指定しています。
  2. 前述(1)の 回転範囲を 180°にした例です。
  3. 前述(1)の 回転範囲を 180°にし、処理対象領域(矩形)の高さを半分にした例です。
  4. 前述(1)の 処理対象領域(矩形)の高さを半分にした例です。
  5. 前述(1)の 回転範囲を -360°にした例です。文字列が反転しています。
  6. 前述(1)の 回転範囲を -180°にした例です。文字列が反転しています。
  7. 前述(1)の 回転開始角を 270°にした例です。
  8. 前述(1)の 処理対象領域(矩形)の幅を 0.8 倍にした例です。

[↑戻る]


濃度補間方法:

濃度補間法は、以下の3つから指定することができます。 詳細については、SamplingMode の説明をご参照ください。

  • NearestNeighbor ... 最近傍法により濃度補間を行います。
  • Bilinear ... 共一次線形補間により濃度補間を行います。
  • Cubic ... 三次畳み込み法により濃度補間を行います。
※注)
処理対象画像の画像種別が BIN の場合は、濃度補間法は無効です。 常に NearestNeighbor で処理されます。

[↑戻る]

Examples


サンプルコード (極座標変換):

極座標変換の処理例:
回転するCD−ROMをラインセンサで撮像した画像(下図【入力画像】)を極座標変換して、 元の円形の状態(下図【出力画像】)に復元する処理例を示します。

【入力画像】


【出力画像】


ソースコード:

C# Copy imageCopy
//    $Revision: 1.3 $

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using fvalgcli;    // FvPluginXXXX attribute requires fvalgcli

namespace User.SampleCode
{
    public partial class PolarTrans
    {
        // ============================================================
        /// <summary>
        /// 極座標変換クラス.
        /// </summary>
        [FvPluginExecute]
        public void PolarTransClass()
        {
            // 1) インスタンスの準備.
            FVIL.PolarTrans.CFviPolarTrans parser = new FVIL.PolarTrans.CFviPolarTrans();
            FVIL.Data.CFviImage src = new FVIL.Data.CFviImage();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();

            // 2) 処理対象画像の取り込み.
            FVIL.File.Function.LoadImageFile(Defs.TestImageDir + "/disk_left.png", src, FVIL.PixelMode.Unpacking);

            // 3) 処理対象画像の有効性検査.
            int valid = FVIL.PolarTrans.CFviPolarTrans.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.PolarTrans.CFviPolarTrans.CheckValidity");

            // 4) 画像処理準備 (共通)
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;

            // 5) パラメータ設定.
            parser.Invert = false;            // false: 矩形→円形.
            parser.ClearBackMode = true;
            parser.SamplingMode = FVIL.PolarTrans.SamplingMode.Bilinear;
            parser.Param.CoordinateMode = FVIL.PolarTrans.CoordinateMode.Left;

            FVIL.PolarTrans.CFviPolarTransParam param = parser.Param;
            param.CoordinateMode = FVIL.PolarTrans.CoordinateMode.Left;
            param.OriginIn = new FVIL.Data.CFviPoint(src.Window.X,src.Window.Y);
            param.Width = src.Window.Width;
            param.Height = src.Window.Height;
            param.OriginOut = new FVIL.Data.CFviPoint(param.Width,param.Width);
            param.Radius = param.Width;
            param.StartAngle = new FVIL.Data.CFviAngle(270.0);
            param.RangeAngle = new FVIL.Data.CFviAngle(360.0);

            // 5-2) 出力画像の有効化.
            parser.Validate(1);    // 有効化.

            // 6) 画像処理実行.
            parser.Execute();

            // E) 処処理結果画像の保存.
            FVIL.File.Function.SaveImageFile(Defs.ResultDir + "/PolarTrans.PolarTrans.png", dst);
        }
    }
}


Visual Basic Copy imageCopy
'    $Revision: 1.1 $

Imports System.Collections.Generic
Imports System.Text
Imports System.Drawing
Imports fvalgcli
' FvPluginXXXX attribute requires fvalgcli
Namespace SampleCode
    Public Partial Class PolarTrans
        ' ============================================================
        ''' <summary>
        ''' 極座標変換クラス.
        ''' </summary>
        <FvPluginExecute> _
        Public Sub PolarTransClass()
            ' 1) インスタンスの準備.
            Dim parser As New FVIL.PolarTrans.CFviPolarTrans()
            Dim src As New FVIL.Data.CFviImage()
            Dim dst As New FVIL.Data.CFviImage()

            ' 2) 処理対象画像の取り込み.
            FVIL.File.[Function].LoadImageFile(Defs.TestImageDir & "/disk_left.png", src, FVIL.PixelMode.Unpacking)

            ' 3) 処理対象画像の有効性検査.
            Dim valid As Integer = FVIL.PolarTrans.CFviPolarTrans.CheckValidity(src)
            If valid <> FVIL.ErrorCode._SUCCESS Then
                Throw New FVIL.CFviException(valid, "FVIL.PolarTrans.CFviPolarTrans.CheckValidity")
            End If

            ' 4) 画像処理準備 (共通)
            parser.SrcImages(0) = src
            parser.DstImages(0) = dst

            ' 5) パラメータ設定.
            parser.Invert = False
            ' false: 矩形→円形.
            parser.ClearBackMode = True
            parser.SamplingMode = FVIL.PolarTrans.SamplingMode.Bilinear
            parser.Param.CoordinateMode = FVIL.PolarTrans.CoordinateMode.Left

            Dim param As FVIL.PolarTrans.CFviPolarTransParam = parser.Param
            param.CoordinateMode = FVIL.PolarTrans.CoordinateMode.Left
            param.OriginIn = New FVIL.Data.CFviPoint(src.Window.X, src.Window.Y)
            param.Width = src.Window.Width
            param.Height = src.Window.Height
            param.OriginOut = New FVIL.Data.CFviPoint(param.Width, param.Width)
            param.Radius = param.Width
            param.StartAngle = New FVIL.Data.CFviAngle(270.0)
            param.RangeAngle = New FVIL.Data.CFviAngle(360.0)

            ' 5-2) 出力画像の有効化.
            parser.Validate(1)
            ' 有効化.
            ' 6) 画像処理実行.
            parser.Execute()

            ' E) 処処理結果画像の保存.
            FVIL.File.[Function].SaveImageFile(Defs.ResultDir & "/PolarTrans.PolarTrans.png", dst)
        End Sub
    End Class
End Namespace

[↑戻る]


サンプルコード (逆変換):

逆変換の処理例:
CD−ROMの中心に円形状に刻印された文字を直線状に変換する処理例を示します。
変換を行う前に処理対象(円形)の中心位置を取得する必要があります。 ここでは、
円ハフ検出 を用いています。
極座標変換の逆変換処理については、ソースコード(1) をご参照ください。 円ハフ検出による中心位置の取得処理については、ソースコード(2)をご参照ください。

【入力画像】


【中心位置】


【出力画像】


ソースコード(1): 円形から矩形への逆変換

C# Copy imageCopy
//    $Revision: 1.3 $

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using fvalgcli;    // FvPluginXXXX attribute requires fvalgcli

namespace User.SampleCode
{
    public partial class PolarTrans
    {
        // ============================================================
        /// <summary>
        /// 極座標変換クラス.
        /// </summary>
        [FvPluginExecute]
        public void PolarTransInvert()
        {
            // 1) インスタンスの準備.
            FVIL.PolarTrans.CFviPolarTrans parser = new FVIL.PolarTrans.CFviPolarTrans();
            FVIL.Data.CFviImage src = new FVIL.Data.CFviImage();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();

            // 2) 処理対象画像の取り込み.
            FVIL.File.Function.LoadImageFile(Defs.TestImageDir + "/disk_cd_01.png", src, FVIL.PixelMode.Unpacking);

            // 3) 処理対象画像の有効性検査.
            if( FVIL.ErrorCode._SUCCESS != FVIL.PolarTrans.CFviPolarTrans.CheckValidity( src ) )
                return;

            // 4) 画像処理準備.
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;

            // 5-1) パラメータ設定.
            parser.Invert = true;            // true: 円形→矩形.
            parser.ClearBackMode = true;
            parser.SamplingMode = FVIL.PolarTrans.SamplingMode.NearestNeighbor;

            // --- 円形領域の中心位置の取得.
            double target = 91/2.0;        // 目標の円半径 (画像によって調整が必要)
            double tie = 24;            // 目標の円の帯幅 (画像によって調整が必要)
            FVIL.Data.CFviPoint    center = new FVIL.Data.CFviPoint();    // 検出した円中心.
            double radius;                // 変換する円半径.
            try
            {
                center = get_center( src, target-(tie/4.0), target+(tie/4.0) );
                radius = (center.X<center.Y) ? center.X : center.Y;
            }
            catch( FVIL.CFviException ex )
            {
                throw new FVIL.CFviException(ex.ErrorCode, "get_center", "Failed to get a center point of circle.");
            }

            // --- パラメータ構造クラス.
            FVIL.PolarTrans.CFviPolarTransParam param = parser.Param;
            param.CoordinateMode = FVIL.PolarTrans.CoordinateMode.Lower;
            // --- 入力: 円形領域の設定.
            param.OriginOut = center;
            param.Radius = radius;
            param.StartAngle = new FVIL.Data.CFviAngle(235.0);    // (!) 画像によって調整が必要.
            param.RangeAngle = new FVIL.Data.CFviAngle(360.0);
            // --- 出力: 矩形領域の設定.
            param.OriginIn = new FVIL.Data.CFviPoint(0,radius-1);
            param.Width = 2 * FVIL.Math.Pi * (target+(tie/2.0));    // 目標の円の円周よりやや外側.
            param.Height = radius;

            // 5-2) 出力画像の有効化.
            parser.Validate(1);        // 有効化.

            // 6) 画像処理実行.
            parser.Execute();

            // E) 処理結果画像の保存.
            FVIL.File.Function.SaveImageFile(Defs.ResultDir + "/PolarTrans.PolarTransInvert.png", dst);
        }
    }
}


Visual Basic Copy imageCopy
'    $Revision: 1.1 $

Imports System.Collections.Generic
Imports System.Text
Imports System.Drawing
Imports fvalgcli
' FvPluginXXXX attribute requires fvalgcli
Namespace SampleCode
    Public Partial Class PolarTrans
        ' ============================================================
        ''' <summary>
        ''' 極座標変換クラス.
        ''' </summary>
        <FvPluginExecute> _
        Public Sub PolarTransInvert()
            ' 1) インスタンスの準備.
            Dim parser As New FVIL.PolarTrans.CFviPolarTrans()
            Dim src As New FVIL.Data.CFviImage()
            Dim dst As New FVIL.Data.CFviImage()

            ' 2) 処理対象画像の取り込み.
            FVIL.File.[Function].LoadImageFile(Defs.TestImageDir & "/disk_cd_01.png", src, FVIL.PixelMode.Unpacking)

            ' 3) 処理対象画像の有効性検査.
            If FVIL.ErrorCode._SUCCESS <> FVIL.PolarTrans.CFviPolarTrans.CheckValidity(src) Then
                Return
            End If

            ' 4) 画像処理準備.
            parser.SrcImages(0) = src
            parser.DstImages(0) = dst

            ' 5-1) パラメータ設定.
            parser.Invert = True
            ' true: 円形→矩形.
            parser.ClearBackMode = True
            parser.SamplingMode = FVIL.PolarTrans.SamplingMode.NearestNeighbor

            ' --- 円形領域の中心位置の取得.
            Dim target As Double = 91 / 2.0
            ' 目標の円半径 (画像によって調整が必要)
            Dim tie As Double = 24
            ' 目標の円の帯幅 (画像によって調整が必要)
            Dim center As New FVIL.Data.CFviPoint()
            ' 検出した円中心.
            Dim radius As Double
            ' 変換する円半径.
            Try
                center = get_center(src, target - (tie / 4.0), target + (tie / 4.0))
                radius = If((center.X < center.Y), center.X, center.Y)
            Catch ex As FVIL.CFviException
                Throw New FVIL.CFviException(ex.ErrorCode, "get_center", "Failed to get a center point of circle.")
            End Try

            ' --- パラメータ構造クラス.
            Dim param As FVIL.PolarTrans.CFviPolarTransParam = parser.Param
            param.CoordinateMode = FVIL.PolarTrans.CoordinateMode.Lower
            ' --- 入力: 円形領域の設定.
            param.OriginOut = center
            param.Radius = radius
            param.StartAngle = New FVIL.Data.CFviAngle(235.0)
            ' (!) 画像によって調整が必要.
            param.RangeAngle = New FVIL.Data.CFviAngle(360.0)
            ' --- 出力: 矩形領域の設定.
            param.OriginIn = New FVIL.Data.CFviPoint(0, radius - 1)
            param.Width = 2 * FVIL.Math.Pi * (target + (tie / 2.0))
            ' 目標の円の円周よりやや外側.
            param.Height = radius

            ' 5-2) 出力画像の有効化.
            parser.Validate(1)
            ' 有効化.
            ' 6) 画像処理実行.
            parser.Execute()

            ' E) 処理結果画像の保存.
            FVIL.File.[Function].SaveImageFile(Defs.ResultDir & "/PolarTrans.PolarTransInvert.png", dst)
        End Sub
    End Class
End Namespace

ソースコード(2): 円ハフ検出による中心位置の取得

C# Copy imageCopy
//    $Revision: 1.2 $

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace User.SampleCode
{
    public partial class PolarTrans
    {
        // ============================================================
        /// <summary>
        /// ディスクの中心座標の取得.
        /// </summary>
        internal FVIL.Data.CFviPoint get_center(FVIL.Data.CFviImage image, double radius_min, double radius_max)
        {
            FVIL.Data.CFviPoint    center = new FVIL.Data.CFviPoint(0,0);

            // -) 有効性の検査.
            int    valid = FVIL.Hough.CFviCircleHoughSobelEdge.CheckValidity(image);
            if( valid != FVIL.ErrorCode._SUCCESS )
                throw new FVIL.CFviException(valid,"FVIL.Hough.CFviCircleHoughSobelEdge.CheckValidity");

            // -) インスタンスの準備.
            FVIL.Hough.CFviCircleHoughSobelEdge parser = new FVIL.Hough.CFviCircleHoughSobelEdge();

            // -) 画像処理準備.
            parser.SrcImages[0] = image;

            // -) パラメータ設定 (本体)
            FVIL.Hough.CFviCircleHoughParam param = parser.Param;
            param.Resolution = 1.0;
            param.RadiusMin = radius_min;
            param.RadiusMax = radius_max;
            param.QRange = 30;
            param.EdgePercent = 20;
            param.MinScore = 8;
            param.ObjectColor = FVIL.Hough.ObjectColor.BlackOrWhite;
            param.MergeCenter = 2;
            param.MergeRadius = 1;

            // -) パラメータ設定 (エッジ検出部分)
            FVIL.Edge.CFviEdge2DSobelParam param_edge = parser.ParamEdge;
            param_edge.EdgeThreshold = 120;
            param_edge.NmsLength = 1;

            // -) 画像処理実行.
            parser.Execute();

            // -) スコア最大値の円を取得.
            FVIL.Data.CFviCircle max_circle = new FVIL.Data.CFviCircle();
            int max_score = 0;
            for(int i = 0; i < parser.Result.Count; i++ )
            {
                FVIL.Hough.CFviCircleHoughData data = parser.Result[i];
                if( max_score < data.Score )
                {
                    max_score = data.Score;
                    max_circle.Center = data.Center;
                    max_circle.Radius = data.Radius;
                }
            }
            center = max_circle.Center;

            // E) 確認用.
            {
                // 画像表示の準備.
                FVIL.GDI.CFviDisplay display = new FVIL.GDI.CFviDisplay();
                display.Image = image;
                display.DisplayRect = image.Window;

                // オーバレイの生成.
                FVIL.GDI.CFviOverlay pOverlay0 = new FVIL.GDI.CFviOverlay();
                pOverlay0.Scaling = true;
                display.Overlays.Add(pOverlay0);

                // 描画図形の生成と追加.

                // --- 円データ生成.
                FVIL.GDI.CFviGdiCircle circle = new FVIL.GDI.CFviGdiCircle(max_circle);
                circle.Pen.Color = System.Drawing.Color.Red;

                FVIL.GDI.CFviGdiPoint point = new FVIL.GDI.CFviGdiPoint(circle.Center);
                point.Pen.Color = System.Drawing.Color.Red;
                point.Style = FVIL.GDI.FigureStyle.Cross;
                point.Size = new System.Drawing.Size( 10, 10 );

                // --- オーバレイへ追加.
                pOverlay0.Figures.Add( circle );
                pOverlay0.Figures.Add( point );

                // 画像保存.
                FVIL.Data.CFviImage canvas = new FVIL.Data.CFviImage();
                display.SaveImage( canvas, display.DisplayRect, 1.0 );
                FVIL.File.Function.SaveImageFile(Defs.ResultDir + "/PolarTrans.get_center.png", canvas);
            }

            return center;
        }
    }
}


Visual Basic Copy imageCopy
'    $Revision: 1.1 $

Imports System.Collections.Generic
Imports System.Text
Imports System.Drawing

Namespace SampleCode
    Public Partial Class PolarTrans
        ' ============================================================
        ''' <summary>
        ''' ディスクの中心座標の取得.
        ''' </summary>
        Friend Function get_center(image As FVIL.Data.CFviImage, radius_min As Double, radius_max As Double) As FVIL.Data.CFviPoint
            Dim center As New FVIL.Data.CFviPoint(0, 0)

            ' -) 有効性の検査.
            Dim valid As Integer = FVIL.Hough.CFviCircleHoughSobelEdge.CheckValidity(image)
            If valid <> FVIL.ErrorCode._SUCCESS Then
                Throw New FVIL.CFviException(valid, "FVIL.Hough.CFviCircleHoughSobelEdge.CheckValidity")
            End If

            ' -) インスタンスの準備.
            Dim parser As New FVIL.Hough.CFviCircleHoughSobelEdge()

            ' -) 画像処理準備.
            parser.SrcImages(0) = image

            ' -) パラメータ設定 (本体)
            Dim param As FVIL.Hough.CFviCircleHoughParam = parser.Param
            param.Resolution = 1.0
            param.RadiusMin = radius_min
            param.RadiusMax = radius_max
            param.QRange = 30
            param.EdgePercent = 20
            param.MinScore = 8
            param.ObjectColor = FVIL.Hough.ObjectColor.BlackOrWhite
            param.MergeCenter = 2
            param.MergeRadius = 1

            ' -) パラメータ設定 (エッジ検出部分)
            Dim param_edge As FVIL.Edge.CFviEdge2DSobelParam = parser.ParamEdge
            param_edge.EdgeThreshold = 120
            param_edge.NmsLength = 1

            ' -) 画像処理実行.
            parser.Execute()

            ' -) スコア最大値の円を取得.
            Dim max_circle As New FVIL.Data.CFviCircle()
            Dim max_score As Integer = 0
            For i As Integer = 0 To parser.Result.Count - 1
                Dim data As FVIL.Hough.CFviCircleHoughData = parser.Result(i)
                If max_score < data.Score Then
                    max_score = data.Score
                    max_circle.Center = data.Center
                    max_circle.Radius = data.Radius
                End If
            Next
            center = max_circle.Center

            ' E) 確認用.
            If True Then
                ' 画像表示の準備.
                Dim display As New FVIL.GDI.CFviDisplay()
                display.Image = image
                display.DisplayRect = image.Window

                ' オーバレイの生成.
                Dim pOverlay0 As New FVIL.GDI.CFviOverlay()
                pOverlay0.Scaling = True
                display.Overlays.Add(pOverlay0)

                ' 描画図形の生成と追加.

                ' --- 円データ生成.
                Dim circle As New FVIL.GDI.CFviGdiCircle(max_circle)
                circle.Pen.Color = System.Drawing.Color.Red

                Dim point As New FVIL.GDI.CFviGdiPoint(circle.Center)
                point.Pen.Color = System.Drawing.Color.Red
                point.Style = FVIL.GDI.FigureStyle.Cross
                point.Size = New System.Drawing.Size(10, 10)

                ' --- オーバレイへ追加.
                pOverlay0.Figures.Add(circle)
                pOverlay0.Figures.Add(point)

                ' 画像保存.
                Dim canvas As New FVIL.Data.CFviImage()
                display.SaveImage(canvas, display.DisplayRect, 1.0)
                FVIL.File.[Function].SaveImageFile(Defs.ResultDir & "/PolarTrans.get_center.png", canvas)
            End If

            Return center
        End Function
    End Class
End Namespace

[↑戻る]