9

JavaCVを使用して形状識別プロジェクトを開発していますが、特定の画像のU形状を識別するためのOpenCVコードをいくつか見つけました。JavaCVに変換しようとしましたが、同じ出力が得られません。このOpenCVコードをJavaCVに変換するのを手伝ってもらえますか?

これはOpenCVコードです:

import cv2
import numpy as np

img = cv2.imread('sofud.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,1)
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    x,y,w,h = cv2.boundingRect(cnt)
    if 10 < w/float(h) or w/float(h) < 0.1:
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2)

cv2.imshow('res',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

これは期待される出力です

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

これは変換されたコードです:

import com.googlecode.javacpp.Loader;
import com.googlecode.javacv.CanvasFrame;
import static com.googlecode.javacpp.Loader.*;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
import java.io.File;
import javax.swing.JFileChooser;

public class TestBeam {
    public static void main(String[] args) {
        CvMemStorage storage=CvMemStorage.create();
        CvSeq squares = new CvContour();
        squares = cvCreateSeq(0, sizeof(CvContour.class), sizeof(CvSeq.class), storage);
        JFileChooser f=new JFileChooser();
        int result=f.showOpenDialog(f);//show dialog box to choose files
            File myfile=null;
            String path="";
        if(result==0){
            myfile=f.getSelectedFile();//selected file taken to myfile
            path=myfile.getAbsolutePath();//get the path of the file
        }
        IplImage src = cvLoadImage(path);//hear path is actual path to image
        IplImage grayImage    = IplImage.create(src.width(), src.height(), IPL_DEPTH_8U, 1);
        cvCvtColor(src, grayImage, CV_RGB2GRAY);
        cvThreshold(grayImage, grayImage, 127, 255, CV_THRESH_BINARY);
        CvSeq cvSeq=new CvSeq();
        CvMemStorage memory=CvMemStorage.create();
        cvFindContours(grayImage, memory, cvSeq, Loader.sizeof(CvContour.class), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
        System.out.println(cvSeq.total());
        for (int i = 0; i < cvSeq.total(); i++) {
            CvRect rect=cvBoundingRect(cvSeq, i);
            int x=rect.x(),y=rect.y(),h=rect.height(),w=rect.width();
            if (10 < (w/h) || (w/h) < 0.1){
                cvRectangle(src, cvPoint(x, y), cvPoint(x+w, y+h), CvScalar.RED, 1, CV_AA, 0);
                //cvSeqPush(squares, rect);
            }
        }
        CanvasFrame cnvs=new CanvasFrame("Beam");
        cnvs.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
        cnvs.showImage(src);
        //cvShowImage("Final ", src);

    }
}

これは私が得た出力です。誰かがこの問題を解決するのを手伝ってくれませんか?

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

4

3 に答える 3

5

編集:これが最も興味深い発見です-私はあなたが輪郭を正しく反復していないと思います-あなたは次のようなことをするべきです:

CvRect rect = cvBoundingRect(cvGetSeqElem(cvSeq, i),0); //python default?

または:

// ... 
CvSeq contours = new CvSeq();
CvSeq ptr = new CvSeq();
CvRect rect = null;
// ...
cvFindContours(..., contours, ...);

for (ptr = contours; ptr != null; ptr = ptr.h_next()) {
    rect =  cvBoundingRect(ptr, 0);
    // ... Draw the box if meets criteria
}

まず、比率の計算に関してはpstが正しいと思います。つまり、フロートする幅をキャストする必要があります。

次に、使用しているPythonCOLOR_BGR2GRAYとJavaでグレー画像を作成している場合CV_RGB2GRAY、まったく異なるグレー画像が表示される可能性があることがわかります。両方のプログラムにいくつかのデバッグ手順を追加して、一時的な灰色の画像を保存し、それらを比較して、trueの値x,y,whwhenの値を出力し(10 < (w/h) || (w/h) < 0.1)ます。

もう1つのことは、JavaソリューションでCV_RETR_CCOMPは輪郭を取得するために使用し、PythonソリューションでCV_RETR_LISTはドキュメントに従って使用することです。

CV_RETR_LISTは、階層関係を確立せずにすべての輪郭を取得します。CV_RETR_CCOMPは、すべての輪郭を取得し、それらを2レベルの階層に編成します。最上位レベルはコンポーネントの外部境界であり、2番目のレベルは穴の境界です。接続されたコンポーネントの穴の中に別の輪郭がある場合でも、それはトップレベルに配置されます

したがって、最初に両方のプログラムのすべてのcvのパラメーターが同じであることを再確認し、次にデバッグ手順を追加して、中間変数に同じデータが含まれていることを確認します。

于 2012-07-12T14:15:06.640 に答える
3

タイププロモーションを確認してください。例:

if (10 < (w/h) || (w/h) < 0.1){

..非常に疑わしいです。浮動小数点除算を取得するには、オペランドの1つ(または両方)が少なくともa float(および同様doubleに二重除算の場合)である必要があります。それ以外の場合は、この場合のように、整数除算です。(元のコードにも昇格があることに注意してくださいfloat。)

例えば:

 float ratio = (float)w/h; // (float / int) => (float / float) -> float
 if (10 < ratio || ratio < 0.1 ) { 

(これがここで問題かどうかはわかりませんが。)

ハッピーコーディング!

于 2012-07-09T03:13:12.267 に答える
2

このコードは私のために機能し、私はcvSeq = cvSeq.h_next();を置くだけです。プログラムにラインインし、forループを削除してthetのwhileループを追加します。

    package Beam;
    import com.googlecode.javacpp.Loader;
    import com.googlecode.javacv.CanvasFrame;
    import static com.googlecode.javacpp.Loader.*;
    import static com.googlecode.javacv.cpp.opencv_core.*;
    import static com.googlecode.javacv.cpp.opencv_imgproc.*;
    import static com.googlecode.javacv.cpp.opencv_highgui.*;
    import java.io.File;
    import javax.swing.JFileChooser;

    public class TestBeam2 {
        public static void main(String[] args) {
            JFileChooser f=new JFileChooser();
            int result=f.showOpenDialog(f);//show dialog box to choose files
                File myfile=null;
                String path="";
            if(result==0){
                myfile=f.getSelectedFile();//selected file taken to myfile
                path=myfile.getAbsolutePath();//get the path of the file
            }
            IplImage src = cvLoadImage(path);//hear path is actual path to image
            IplImage grayImage    = IplImage.create(src.width(), src.height(), IPL_DEPTH_8U, 1);
            cvCvtColor(src, grayImage, CV_RGB2GRAY);
            cvThreshold(grayImage, grayImage, 127, 255, CV_THRESH_BINARY);
            CvSeq cvSeq=new CvSeq();
            CvMemStorage memory=CvMemStorage.create();
            cvFindContours(grayImage, memory, cvSeq, Loader.sizeof(CvContour.class), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

            while (cvSeq != null && !cvSeq.isNull()) {
                CvRect rect=cvBoundingRect(cvSeq, 0);
                int x=rect.x(),y=rect.y(),h=rect.height(),w=rect.width();
                if (10 < w/h || w/h < 0.1){
                    cvRectangle(src, cvPoint(x, y), cvPoint(x+w, y+h), CvScalar.RED, 1, CV_AA, 0);
                }
                cvSeq=cvSeq.h_next();
            }
            CanvasFrame cnvs=new CanvasFrame("Beam");
            cnvs.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
            cnvs.showImage(src);
            //cvShowImage("Final ", src);
        }
    }
于 2012-07-17T12:44:04.630 に答える