14

下の画像があります。このオブジェクトを2つに分割する線を検出したいと思います。どちらが最善の方法ですか?ハフ変換を試しましたが、オブジェクトが検出するのに十分な大きさでない場合があります。アイデアはありますか?

ありがとう!

ここに画像の説明を入力してください

4

1 に答える 1

40

通常、ライン検出にはハフ変換が使用されます。

しかし、それがうまくいかない場合は、フィッティングラインも良い選択肢です.

詳細とパラメーターについては、OpenCVの fitline関数を確認してください。

あなたはすでにハフラインを試しているので、OpenCV-Python を使用して、ここでフィッティングラインを示します:

# Load image, convert to grayscale, threshold and find contours
img = cv2.imread('lail.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hier = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]

# then apply fitline() function
[vx,vy,x,y] = cv2.fitLine(cnt,cv2.cv.CV_DIST_L2,0,0.01,0.01)

# Now find two extreme points on the line to draw line
lefty = int((-x*vy/vx) + y)
righty = int(((gray.shape[1]-x)*vy/vx)+y)

#Finally draw the line
cv2.line(img,(gray.shape[1]-1,righty),(0,lefty),255,2)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

以下は私が得た結果です:

ここに画像の説明を入力

ここに画像の説明を入力

編集 :

オブジェクトを 2 つに分割する線を見つけたい場合は、最初に適合する線を見つけ、次にそれに垂直な線を見つけます。

そのために、以下のコードを cv2.fitLine() 関数の下に追加します。

nx,ny = 1,-vx/vy
mag = np.sqrt((1+ny**2))
vx,vy = nx/mag,ny/mag

そして、以下は私が得た結果です:

ここに画像の説明を入力

ここに画像の説明を入力

それが役に立てば幸い !!!

アップデート :

以下は、要求された最初のケ​​ースの Python コードの C++ コードです。コードは私にとってはうまく機能します。出力は上記と同じです:

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv/cv.h>

using namespace std;
using namespace cv;

int main()
{
    cv::Mat img, gray,thresh;
    vector<vector<Point>> contours;
    Vec4f lines;

    img = cv::imread("line.png");
    cv::cvtColor(img,gray,cv::COLOR_BGR2GRAY);
    cv::threshold(gray,thresh,127,255,cv::THRESH_BINARY);
    cv::findContours(thresh,contours,cv::RETR_LIST,cv::CHAIN_APPROX_SIMPLE);
    cv::fitLine(Mat(contours[0]),lines,2,0,0.01,0.01);

    //lefty = int((-x*vy/vx) + y)
    //righty = int(((gray.shape[1]-x)*vy/vx)+y)
    int lefty = (-lines[2]*lines[1]/lines[0])+lines[3];
    int righty = ((gray.cols-lines[2])*lines[1]/lines[0])+lines[3];

    cv::line(img,Point(gray.cols-1,righty),Point(0,lefty),Scalar(255,0,0),2);

    cv::imshow("img",img);
    cv::waitKey(0);
    cv::destroyAllWindows();
}
于 2013-01-07T08:58:41.313 に答える