第 16 章: ハフ変換

  • ハフ変換は、画像内の線、円、その他の単純な形状を見つける方法です。
  • ハフ変換は、投票に似た方法を使用して、現在の画像に設定されている形状を取得します。この変換は、1962 年に Paul Hough (Hough) によって初めて提案されました。

オリジナルのハフ変換は直線の検出にのみ使用できましたが、開発後のハフ変換は直線だけでなく、円や楕円などの他の単純なグラフィック構造も認識できるようになりました。実際、パラメータ方程式で表現できる物体であれば、ハフ変換による検出に適している。

以下では主にハフ線変換ハフ円変換について紹介します。

  • ハフ線変換は、画像内の線を見つけるために使用されます。OpenCVでは関数 cv2.HoughLines() と関数 cv2.HoughLinesP() で実現できます。
  • ハフ円変換は、画像内の円を見つけるために使用されます。関数 cv2.HoughCircles() を使用して実現します。

1. ハフ線形変換:

OpenCV では、ハフ線変換を実現する関数 cv2.HoughLines() と関数 cv2.HoughLinesP() を提供しています。以下では、まずハフ変換の基本原理を紹介し、次にこれら 2 つの関数の基本的な使用法を紹介します。

1. ハフの線形変換原理:

問題の説明を容易にするために、まず、よく知られたデカルト座標系 (つまり、デカルト空間に対応する平面デカルト座標系) を例として取り上げ、ハフ変換の基本原理を説明します。デカルト座標系に対応して、ハフ座標系 (ハフ空間に相当) を構築します。ハフ座標系では、横軸はデカルト座標系の直線の傾き k を使用し、縦軸はデカルト座標系の直線の切片 b を使用します。

まず、ハフ空間のデカルト空間における直線のマッピングを観察します。たとえば、下図の左の図はデカルト xy 座標系 (デカルト空間)、右の図はハフ kb 座標系 (ハフ空間) です。デカルト空間には直線 y=k0x+b0 があり、この直線の切片 k0 は既知の定数であり、切片 b0 も既知の定数です。直線をハフ空間にマッピングし、既知の点 (k0, b0) を見つけて、マッピングを完了します。

画像-20211208155701791

上記の分析から、デカルト空間の直線は k の傾きと b の切片を持ち、ハフ空間の点 (k,b) にマッピングされることがわかります。あるいは、ハフ空間上の点(k0, b0)は、直線y=k0x+b0であるデカルト空間に写像されると理解することもできる。

ここでは、異なる空間(座標系)間の対応関係を表すために「マッピング」という言葉を使いますが、これは「決まっている」とも表現できます。たとえば、上記の関係は次のように表すことができます。

  • デカルト空間の線は、ハフ空間の点を定義します。
  • ハフ空間内の点は、デカルト空間内の線を定義します。

次に、ハフ空間のデカルト空間内の点のマッピングを観察します。下図のように、直交空間上に点(x0,y0)があり、この点を通る直線はy0=kx0+bと表せます。このうち、(x0, y0) は既知の定数、(k, b) は変数です。

y0=kx0+bという式は、算術演算の左右シフトによりb=−x0k+y0と表すことができます。点 (x0, y0) をハフ空間にマッピングすると、直線に示すように、対応する直線の傾きは −x0、切片は y0、つまり b=−x0k+y0 と考えることができます。下の図の右側の線です。

画像-20211208155944679

上記の分析から、次のことがわかります。

  • デカルト空間の点 (x0, y0) は、直線 b=−x0k+y0 であるハフ空間にマッピングされます。
  • ハフ空間の直線 b=−x0k+y0 は、点 (x0, y0) であるデカルト空間にマッピングされます。

デカルト空間の 2 点がハフ空間にマッピングされる状況を見てみましょう。例えば下図では、左図のデカルト空間に(x0, y0)と(x1, y1)の2点があり、この2点がハフ空間に写像される様子を解析します。

画像-20211208160054385

理解を容易にするために、デカルト空間のこれら 2 点のハフ空間へのマッピングをさまざまな角度から分析します。

  • 角度 1: デカルト空間の点がハフ空間の線にマッピングされます。

    デカルト空間には、任意の 2 つの点 (x0, y0)、(x1, y1) があります。ハフ空間では、これら 2 つの点は 2 つの異なる直線に対応します。もちろん、解析により、一方の直線は b=−x0k+y0 であり、もう一方の直線は b=−x1k+y1 であることがわかります。

  • 角度 2: デカルト空間の線がハフ空間の点にマッピングされる

    デカルト空間には、任意の 2 つの点 (x0, y0)、(x1, y1) があります。これら 2 つの点は直線で結ばれなければなりません。これらを結ぶ直線は y=k1x+b1 とマークされ、線の切片と傾きは (k1, b1) となります。つまり、直線はハフ空間上の点(k1、b1)に写像される。

上記の分析から、次のことがわかります。

  • デカルト空間の 2 点は、ハフ空間の (k1,b1) で交差する 2 本の直線にマッピングされます。
  • これら 2 点に対応する直線は、ハフ空間の点 (k1, b1) にマッピングされます。

つまり、角度 1 は線の数を決定し、角度 2 は 2 つの線が交差する点を決定します。

これは、デカルト空間に 2 つの点 A と B がある場合、それらを直線 y=k1x+b1 に接続できることを示しています。すると、ハフ空間の点 (k1,b1) 上に 2 つの直線が存在します。デカルト空間内の 2 つの点 A と B をそれぞれ表します。

デカルト空間の 3 点がハフ空間にマッピングされる状況を見てみましょう。下の図の左側の図はデカルト空間で、そこには 3 つの点 (0,1)、(1,2)、(2,3) があります。

画像-20211208161422534

以下では、デカルト空間のこれら 3 点のハフ空間へのマッピングをさまざまな角度から分析します。

  • 角度 1: デカルト空間の点がハフ空間の線にマッピングされます。

    たとえば、デカルト空間の 3 つの点 (0,1)、(1,2)、(2,3) をハフ空間にマッピングすると、各点は直線に対応し、対応関係は表に示されます。 。画像-20211208161509551

    対応関係によれば、次のことがわかります。

    • デカルト空間の点 (0,1) は、ハフ空間の直線 b=1 に対応します。
    • デカルト空間の点 (1,2) は、ハフ空間の直線 b=-k+2 に対応します。
    • デカルト空間の点 (2,3) は、ハフ空間の直線 b=-2k+3 に対応します。

上記の分析から、デカルト空間の 3 つの点がハフ空間の 3 つの直線にマッピングされていることがわかります。

  • 角度 2: デカルト空間の線がハフ空間の点にマッピングされます。

    たとえば、デカルト空間の 3 つの点 (0,1)、(1,2)、および (2,3) は直線 y=x+1 に対応し、傾き k は 1、切片 b は 1 です。 。直線 y=x+1 は、ハフ空間の点 (1,1) にマッピングされます。

上記の角度 1 と角度 2 の分析から、次のことがわかります。

  • デカルト空間の 3 つの点 (0,1)、(1,2)、および (2,3) は、ハフ空間の点 (1,1) で交差する 3 つの直線にマッピングされます。
  • デカルト空間の 3 点 (0,1)、(1,2)、(2,3) によって形成される直線は、ハフ空間の点 (1,1) にマッピングされます。

これは、デカルト空間に 3 つの点があり、それらを直線 y=k1x+b1 に接続できる場合、ハフ空間では、対応する点 (k1, b1) 上に 3 つの直線があり、対応することを示しています。それぞれデカルト空間の 3 点に変換されます。

これまでのところ、デカルト空間に直線 y=k1x+b1 に接続できる N 個の点がある場合、ハフ空間 (k1 ,b1) には対応する点を通る N 個の直線が存在することがわかりました)。または逆に、ハフ空間で点 (k1, b1) を通過する直線がより多く存在する場合、デカルト空間では、傾きが k1 で切片が 1 である直線上に位置する点がより多く存在することを意味します。 b1 y=k1x+b1 上。

ここで、デカルト空間内のより多くの点がハフ空間にマッピングされる例を見て、上記の観点を検証してみましょう。下の図の左図は 6 つの点があるデカルト空間を示していますが、この 6 点が右図のハフ空間にマッピングされる様子をさまざまな角度から見てみましょう。

画像-20211208162137460

  • 角度 1: デカルト空間の点がハフ空間の線にマッピングされます。

デカルト空間の 6 点: (0,1)、(1,2)、(2,3)、(3,4)、(3,2)、(1,4)、ハフ空間の各点にマッピングは直線に相当し、対応関係は表に示されています。

画像-20211208162418904
対応関係によれば、次のことがわかります。

  • デカルト空間の点 (0,1) は、ハフ空間の直線 b=1 に対応します。
  • デカルト空間の点 (1,2) は、ハフ空間の直線 b=-k+2 に対応します。
  • デカルト空間の点 (2,3) は、ハフ空間の直線 b=-2*k+3 に対応します。
  • デカルト空間の点 (3,4) は、ハフ空間の直線 b=-3*k+4 に対応します。
  • デカルト空間の点 (3,2) は、ハフ空間の直線 b=-3*k+2 に対応します。
  • デカルト空間の点 (1,4) は、ハフ空間の直線 b=-1*k+4 に対応します。

上記の分析から、デカルト空間の 6 つの点がハフ空間の 6 つの直線にマッピングされていることがわかります。

  • 角度 2: デカルト空間の線がハフ空間の点にマッピングされます。

    ここでは、観察しやすいように、デカルト空間内のより多くの点に接続された線が描画されます。点 (0,1)、(1,2)、(2,3)、(3,4) を接続する線 LineA , 点(2,3)、(3,2)、(1,4)を結ぶ直線LineB、点(0,1)、(3,2)を結ぶ直線LineC

    画像-20211208162843769

デカルト空間では、各点の間に多くの直線があることに注意してください。たとえば、点 (1,2) と (3,2) の間、点 (3,2) と (3,4) の間、および点 (1,4) と (3,4) の間に直線があります。ここでは簡略化してあり、上記の直線は描いていない。

以下は、ハフ空間のデカルト空間における 3 つの直線 LineA、LineB、LineC のマッピングを分析します。

  • 直線 LineA は 4 点を通過し、式は y=1 * x+1、傾き k は 1、切片 b は 1 で、ハフ空間の点 A(1,1) に対応します。
  • 直線 LineB は 3 点を通過しており、式は y=-1 * x+5、傾き k は -1、切片 b は 5 で、ハフ関数の点 B(-1,5) に対応します。空。
  • 直線 LineC は 2 点を通過し、式は y=-1/3 * x+1、傾き k は -1/3、切片 b は 1 で、点 C (-1/3) に対応します。 ,1)。

上図からわかるように、右のハフ空間には点Aを通る直線が4本、点Bを通る直線が3本、点Cを通る直線が2本あります。上記の関係を分析すると、次のようになります。

  • ハフ空間には点Aを通る直線が4本あります。点 A はデカルト空間の直線を決定し、その直線は 4 つの点を同時に通過します。つまり、ハフ空間の点 A は、(0,1)、(1,2)、(1,2)、を含むデカルト空間の LineA を決定します。 (2、3)、(3、4)の計4点。
  • ハフ空間には点Bを通る直線が3本あります。点 B はデカルト空間の直線を決定し、その線は同時に 3 点を通過します。つまり、ハフ空間の点 B は、(2,3) を含むデカルト空間の線 B を決定します。点は 3 つあります (3) 、2) および (1、4)。
  • ハフ空間には点Cを通る直線が2本あります。点 C はデカルト空間の直線を決定し、その線は 2 つの点を同時に通過します。つまり、ハフ空間の点 C は、(0,1)、(2,3) を含むデカルト空間の LineC を決定します。合計2点。

まとめると、ハフ空間では、点を通過する直線が多いほど、デカルト空間にマッピングされた直線は、より多くの点で構成されている(通過している)ことを意味します。2 つの点が直線を形成できることはわかっています。ただし、計算ミスにより点が生成されると、その点と他の点も直線を形成することになり、このとき、実際には存在しない直線が虚空に作られることになります。このような状況は可能な限り回避する必要があります。

したがって、計算では、より多くの点で直線を構築し、直線の信頼性を向上させたいと考えています。つまり、直線がより多くの点で構成されているほど、その直線が実際に存在する可能性が高く、信頼性も高くなります。

したがって、直線を選択するためのハフ変換の基本的な考え方は、できるだけ多くの直線が交わる点を選択することです。

上記はすべて、よく知られたデカルト空間を例として説明しています。デカルト空間では、次の形式の x=x0 などの垂直線 LineA が存在する場合があります。

画像-20211208163839539

このとき、傾きkは無限大となり、切片bは値をとることができない。したがって、上図の垂直線 LineA はハフ空間に写像できません。上記の問題を解決するには、図に示すように、直交座標系を極座標系に写像することが考えられます。

画像-20211208164004913

デカルト座標系では、傾き k と切片 b が使用され、直線は (k,b) で表されます。極座標系では、極半径 r (ρ で表すこともあります) と極角 θ、つまり (r, θ) で表されます。極座標の直線は次のように表現できます。

  • r=xcosθ+ysinθ

例えば、上図の直線LineAは、極座標における極半径rと極角θで表すことができます。このうち、rは直線LineAと画像原点Oとの間の距離、パラメータθは直線LineAの垂線LineBとx軸とのなす角度である。この表現では、画像内の直線の角度θは(0~π)であり、rの最大値は画像の対角線の長さになります。この表現方法を使うと、上図の3点で構成される直線を表現するのに非常に便利です。

デカルト空間とハフ空間の間のマッピング関係に似ています。

  • 極座標系の点は、ハフ座標系 (ハフ空間) の線 (曲線) にマッピングされます。
  • 極座標の線はハフ座標の点にマッピングされます。

一般に、極座標の直線は、ハフ座標の点で交差する線の数によって評価できます。ハフ座標系では、点を通過する線が多いほど、極座標系でマッピングされる直線がより多くの点で形成される(通過する)ことを意味します。したがって、直線を選択するためのハフ変換の基本的な考え方は、できるだけ多くの線によって形成される点を選択することです。

通常、閾値が設定されており、ハフ座標系のある点で交わる曲線が閾値に達すると、対応する極座標系に直線が存在する(検出された)とみなします。

上記の内容はハフ変換の原理ですが、上記の原理を全く理解していなくても、OpenCVが提供するハフ変換関数を使用してハフ変換を行うことに影響はありません。OpenCV 自体はブラック ボックスであり、インターフェイス (パラメーター、戻り値) を提供しますが、インターフェイスの正しい使用法をマスターするだけで、内部の動作原理をマスターしなくても画像の問題を正しく処理できます。

OpenCVライブラリやPhotoshopなどの画像処理ソフトウェアも同様の場合があり、使い方をマスターすれば正しい処理結果を得ることができます。画像処理を行う際に、その実現原理などの技術的な詳細を意識する必要はありません。しかし、それがどのように機能するかをさらに理解できれば、私たちの仕事にも大きな利益をもたらすでしょう。

2.ハフライン機能:

OpenCV には、ハフ ライン変換を実装するための関数 cv2.HoughLines() が用意されています。この関数では、操作するソース イメージがバイナリ イメージである必要があるため、ハフ変換またはキャニー エッジ検出の前にソース イメージをバイナリ化する必要があります。

関数 cv2.HoughLines() の構文形式は次のとおりです。

  • Lines=cv2.HoughLines(画像、ρ、θ、閾値)
    • image: 入力イメージ、つまりソース イメージは、8 ビットのシングル チャネル バイナリ イメージである必要があります。別の種類の画像の場合は、ハフ変換を実行する前に、指定された形式に変更する必要があります。
    • rho: ピクセル単位の距離 r の精度。通常、精度 1 が使用されます。
    • theta: 角度θの精度。通常、使用される精度は π/180 です。これは、すべての可能な角度が検索されることを意味します。
    • しきい値: しきい値です。値が小さいほど直線と判定されます。前節の分析によれば、直線を特定する場合には、その直線上に点がいくつあるかを決定する必要があります。線が存在するかどうかを判断する際には、その線が通過する点の数が評価され、その線が通過する点の数がしきい値未満の場合、それらの点はアルゴリズム的に (偶然に) 線を形成していると見なされますが、ソース画像には線が存在しません。しきい値より大きい場合、線は存在するとみなされます。したがって、しきい値が小さい場合はより多くの直線が得られ、しきい値が大きい場合はより少ない直線が得られます。
    • Lines: 戻り値。各要素は浮動小数点数のペアで、検出された直線のパラメーター、つまり (r, θ) を表します。これは numpy.ndarray 型です。

知らせ:

関数 cv2.HoughLines() を使用すると、画像内の線分ではなく直線が検出されるため、検出された直線には端点がありません。したがって、ハフ線変換を実行するときに描く直線は画像全体を通過します。

直線の引き方は、縦方向の直線(垂直線ではなく、縦方向に様々な角度の直線)について、画像の横境界線との距離を計算します(つまり、画像の最初と最後の線) が交差し、これら 2 つの交差の間に線を描きます。水平方向の直線の場合も、画像の最初と最後の列が使用されることを除いて、同様の方法で実行されます。

線を描く際に使用する関数は cv2.line() です。この関数の便利な点は、点の座標が画像の範囲外にある場合でも正しく線を描画するため、交点が画像内にあるかどうかを確認する必要がないことです。関数 cv2.HoughLines() の戻り値の行を走査します。

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('./buliding.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray_img, 50, 150, apertureSize=3)

rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
new_img = rgb_img.copy()
print(lines)
for line in lines:
    rho, theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)

    x0 = a * rho
    y0 = b * rho
    x1 = int(x0 + 1000 * (-b))
    y1 = int(y0 + 1000 * (a))
    x2 = int(x0 - 1000 * (-b))
    y2 = int(y0 - 1000 * (a))
    cv2.line(new_img, (x1, y1), (x2, y2), (0, 0, 255), 2)

plt.subplot(131)
plt.imshow(rgb_img)
plt.axis('off')

plt.subplot(132)
plt.imshow(edges)
plt.axis('off')

plt.subplot(133)
plt.imshow(new_img)
plt.axis('off')

plt.show()

画像-20211208200103945

補足:OpenCVでHoughLinesの2点(x1, y1)と(x2, y2)を計算する方法。

画像-20211209150106449

上図は線分を1000に拡大する方法、つまりr=1000の場合の計算方法を示しています。300、500、800 のいずれかになります。

3.HoughLinesP 関数:

確率的ハフ変換は、基本的なハフ変換アルゴリズムにいくつかの変更を加え、ハフ変換アルゴリズムを最適化したものです。すべての点を考慮するわけではありません。代わりに、ライン検出に十分な点のランダムなサブセットのみが必要です。

直線 (線分) をより適切に判断するために、確率的ハフ変換アルゴリズムでは、直線の選択方法に 2 つの改良も加えられています。

  • **許容される行の最小長。**直線を構成するピクセル数が閾値以上であっても、その直線が非常に短い場合、その直線は判定結果として受け入れられず、直線はほんの数本であるとみなされます。画像内のランダムなピクセル。これはアルゴリズム上の直線関係を構成しますが、実際には、この直線は元の画像には存在しません。
  • **直線を受け入れる場合に許可される最大ピクセル間隔。**直線を構成するピクセル数が閾値以上であっても、ピクセル群間の距離が非常に遠い場合、直線は判定結果として受け入れられず、直線は判定結果として受け入れられません。画像にはほんの数個のピクセルがランダムにアルゴリズムの直線関係を構成しているだけですが、実際にはこの直線は元の画像には存在しません。

確率ハフ変換は、cv2.HoughLinesP() 関数を通じて OpenCV に実装されます。

  • ライン = cv2.HoughLiesP(画像、ロー、シータ、しきい値、minLineLength、maxLineGap)
    • image: 入力イメージ、つまり元のイメージは、8 ビットのシングル チャネル バイナリ イメージである必要があります。他のタイプの画像の場合は、ハフ変換を実行する前に、この指定された形式に変更する必要があります。
    • rho: ピクセル単位の距離 r の精度。通常、精度 1 が使用されます。
    • theta: 角度θの精度です。一般に、使用される精度は np.pi/180 で、検索可能な角度を示します。
    • しきい値: しきい値です。値が小さいほど直線が多く判定され、値が大きいほど直線が少なく判定されます。
    • minLineLength: 「受け入れられる行の最小長」の値を制御するために使用されます。デフォルト値は 0 です。
    • maxLineGap: 許容される同一線上の線分間の最小間隔、つまり、線内の 2 点間の最大間隔を制御するために使用されます。
      2 点間の距離がパラメータ maxLineGap の値を超える場合、2 点は直線上にあるとは見なされません。デフォルト値は 0 です。
    • 行: 戻り値。これは、numpy.ndarray 型の要素で構成されており、各要素は検出された直線のパラメーター (x1, y1)、(x2, y2) を表す浮動小数点数のペアです。
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('buliding.jpg')
grey_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
new_img = rgb_img.copy()

edges = cv2.Canny(grey_img, 150, 200, apertureSize=3)

lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength=100, maxLineGap=30)
for line in lines:
    x1, y1, x2, y2 = line[0]
    cv2.line(new_img, (x1, y1), (x2, y2), (255, 0, 0), 2)

plt.subplot(131)
plt.imshow(rgb_img)
plt.title('img')
plt.axis('off')

plt.subplot(132)
plt.imshow(edges)
plt.title('edges')
plt.axis('off')

plt.subplot(133)
plt.imshow(new_img)
plt.title('rst')
plt.axis('off')

plt.show()

画像-20211209141003077

2. ハフリング変換:

ハフ変換は、直線の検出に使用されるだけでなく、他の幾何学的オブジェクトの検出にも使用できます。実際、パラメータ方程式で表現できる物体であれば、ハフ変換による検出に適している。

ハフ円変換を使用して画像内の円を検出することは、ハフ線変換を使用して直線を検出する原理と似ています。ハフ円変換では、円の半径と円の中心 (x 座標、y 座標) の 3 つのパラメータを考慮する必要があります。OpenCV では、2 ラウンドのスクリーニングが採用されています。最初のラウンドのスクリーニングでは、考えられる円の位置 (中心) が見つかり、第 2 ラウンドでは、最初のラウンドの結果に基づいて半径がスクリーニングされます。

直線を受け入れるかどうかを決定するために使用される 2 つのパラメータ、「受け入れられる線の最小長 (minLineLength)」と「直線を受け入れるときに許可される最大ピクセル間隔 (MaxLineGap)」と同様に、次の目的で使用されるハフ円変換がいくつかあります。円のパラメータ (中心間の最小距離、円の最小半径、円の最大半径) を受け入れるかどうかを決定します。

OpenCV では、ハフ円変換は関数 cv2.HoughCircles() によって実現されます。**この関数は、キャニー エッジ検出とハフ変換を組み合わせたものです。** その文法形式は次のとおりです。

  • 円 = cv2.HoughCircles(画像、メソッド、dp、minDist、param1、param2、minRadius、maxradius)
    • image: 入力イメージ、つまりソース イメージは、8 ビットのシングル チャネル グレースケール イメージです。
    • 方法: 検出方法。OpenCV 4.0.0 より前のバージョンでは、使用可能なパラメータ値は HOUGH_GRADIENT のみです。このパラメータは、ハフ円検出における 2 回の検出に使用される方法を表します。
    • dp: アキュムレータ解像度。分割比であり、画像解像度と中心アキュムレータ解像度の比率を指定するために使用されます。たとえば、dp=1 の場合、入力イメージとアキュムレータは同じ解像度を持ちます。
    • minDist: 円の中心間の最小距離。この値はしきい値として使用され、中心がこの値より小さい円が複数ある場合、1 つだけが検出されます。したがって、値が小さすぎると隣接する複数の円が検出され、値が大きすぎると検出中に一部の円が見逃される可能性があります。
    • param1: このパラメータはデフォルトであり、デフォルト値は 100 です。これは、Canny エッジ検出器の高しきい値に対応します (低しきい値は高しきい値の半分です)。
    • param2: 円の中心で受け取る必要がある投票の数。一次審査で得票数がこの数値を超えたサークルのみが二次審査に参加できます。したがって、値が大きいほど検出される円は少なくなり、値が小さいほど多くの円が検出されます。このパラメータはデフォルトであり、デフォルトではデフォルト値 100 が設定されています。
    • minRadius: 円の半径の最小値。この値より小さい円は検出されません。このパラメータはデフォルトであり、デフォルトではデフォルト値 0 が設定されており、現時点ではこのパラメータは効果がありません。
    • maxRadius: 円の半径の最大値。この値より大きい円は検出されません。このパラメータはデフォルトであり、デフォルトではデフォルト値 0 が設定されており、現時点ではこのパラメータは効果がありません。
    • Circles: 戻り値、円の中心の座標と半径で構成される numpy.ndarray。

画像内のノイズを軽減し、誤った判断を避けるために、関数 cv2.HoughLinesCircles() を呼び出す前にソース画像を平滑化することに特別な注意を払う必要があります。

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('xiangqi.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
new_img = rgb_img.copy()

circles = cv2.HoughCircles(gray_img, cv2.HOUGH_GRADIENT, 1, 100, param1=100, param2=30, minRadius=50, maxRadius=100)
print(circles)
circles = np.uint16(np.around(circles))
print(circles)
for i in circles[0, :]:
    cv2.circle(new_img, (i[0], i[1]), i[2], (255, 0, 0), 10)
    # 圆心
    cv2.circle(new_img, (i[0], i[1]), 2, (255, 0, 0), 10)

plt.subplot(121)
plt.imshow(rgb_img)
plt.title('img')
plt.axis('off')

plt.subplot(122)
plt.imshow(new_img)
plt.title('rst')
plt.axis('off')
plt.show()

画像-20211209145638841

おすすめ

転載: blog.csdn.net/weixin_57440207/article/details/122647052