前提・実現したいこと
現在, OpenCVのハフ変換を用いた直線検出のプログラムを書いており, 検出された直線をX-means法により自動でクラスタリング, また, threshold値(直線検出の際のパラメータ)をループ処理で自動で決めて, どの画像でも一定の結果を出せるようにしたいのですが, ループ処理が上手くいかない状態です.
理想は(threshold値が大きくなるのに反比例してクラスタ数は少なくなっていくので)「threshold値を1ずつ増やしていき, X-meansにより取得したクラスタ数が2になったらループ終了」という条件で処理を行いたいのですが, 関数内での特定箇所のループの仕方が分からず困っています.(現状関数全体のループになってしまっている状態です.)
該当のソースコード
import pandas as pd import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np from pyclustering.cluster.xmeans import xmeans, kmeans_plusplus_initializer from pyclustering.utils import draw_clusters import cv2 IMAGE_PATH = ".png" # 読み込む画像 Z = 35 def main(): image = cv2.imread(IMAGE_PATH) # 画像読み込み image2 = cv2.imread(IMAGE_PATH) # 画像読み込み gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) # グレースケール化 outLineImage = cv2.Canny(gray,15, 22, apertureSize = 3) # 輪郭線抽出 cv2.imwrite("./outLine.png", outLineImage) # ファイル保存 houghList = hough_lines(image, outLineImage) # ハフ変換による直線抽出 cv2.imwrite("./result_hough.png", image) # ファイル保存 draw_cross_points(image, houghList) # 直線リストから交点を描画 cv2.imwrite("./result_hough_cross.png", image) # ファイル保存 # ハフ変換で直線を抽出する関数 def hough_lines(image, outLineImage): global Z lineList = [] lines = cv2.HoughLines(outLineImage, rho=1, theta=np.pi/50, threshold=Z) # ハフ変換で直線抽出 print("hough_lines: ", len(lines)) # print("hough_lines.shape: ", lines.shape) new_lines = np.empty((len(lines), 2)) new_lines = np.reshape(lines, (len(lines), 2)) # print("lines_3",lines) for line in lines: # print("lines_3",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)) # (ρ, θ)の定義 x = (theta * 180/np.pi) y = rho # 直線グラフのプロット plt.xlim(0, 360) # x軸の表示範囲 plt.scatter(x, y, marker=".", label="hough_List") print("rho: ", rho, "theta:", x) lineList.append((x1, y1, x2, y2)) cv2.line(image,(x1,y1),(x2,y2),(0,255,0),2) # 緑色で直線を引く #X-meansによるクラスタリング # クラスタ数1から探索させてみる initial_centers = kmeans_plusplus_initializer(new_lines, 1).initialize() # クラスタリングの実行 instances = xmeans(new_lines, initial_centers, ccore=True) instances.process() # クラスタはget_clustersで取得できる np.set_printoptions(precision=2) clusters = instances.get_clusters() # クラスタの平均は以下で計算できる centers = [] lines = np.array(new_lines) # print("hough_lines.shape2: ", lines.shape) for cluster in clusters: c = lines[cluster, :] centers.append(np.mean(c, axis=0)) #クラスタ数の表示 print("Clusters: ", len(clusters)) print("Cluster", clusters) #threshold値のループ処理 while len(clusters) > 2: print("clusters in while", len(clusters)) if len(clusters) == 2: break Z += 1 print("threshold:", Z) # hough_lines(image, outLineImage) # lines = np.zeros_like(lines) # new_lines = np.zeros_like(new_lines) # Z += 1 return lineList
試したこと
thresholdループ処理のwhile文の箇所で繰り返し処理を行おうとしたのですが, ループ内部に(コメントアウトしてある部分の)hough_lines(image, outLineImage)の関数を入れた(再帰した)場合, 関数全体を(ループ箇所含めて)繰り返してしてしまっており, len(clusters)の値が変わらないためいつまでもループを続けてしまうみたいです.
lines = cv2.HoughLines(outLineImage, rho=1, theta=np.pi/50, threshold=Z) # ハフ変換で直線抽出
の部分のみをループさせたいのですが, どういった書き方にすれば上手くいくか教えていただけたら幸いです.
補足情報(FW/ツールのバージョンなど)
Python3.7, OpenCV4.1.2
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。