Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在HoughCircles()和OpenCV给定的点序列上使用warpPerspective()_Java_Android_Opencv_Transformation - Fatal编程技术网

Java 在HoughCircles()和OpenCV给定的点序列上使用warpPerspective()

Java 在HoughCircles()和OpenCV给定的点序列上使用warpPerspective(),java,android,opencv,transformation,Java,Android,Opencv,Transformation,我试图从透视角度拍摄的图像中检测台球在桌子上的位置。我正在使用getPerspectiveTransform()方法来查找变换矩阵,我想将其仅应用于使用HoughCircles检测到的圆。我试着从一个相当大的梯形变成一个较小的矩形。我不想先对图像进行变换,然后再找到HoughCircles,因为图像太扭曲,HoughCircles无法提供有用的结果 这是我的密码: CvMat mmat = cvCreateMat(3,3,CV_32FC1); double src

我试图从透视角度拍摄的图像中检测台球在桌子上的位置。我正在使用getPerspectiveTransform()方法来查找变换矩阵,我想将其仅应用于使用HoughCircles检测到的圆。我试着从一个相当大的梯形变成一个较小的矩形。我不想先对图像进行变换,然后再找到HoughCircles,因为图像太扭曲,HoughCircles无法提供有用的结果

这是我的密码:

        CvMat mmat = cvCreateMat(3,3,CV_32FC1);
        double srcX1 = 462;
        double srcX2 = 978;
        double srcX3 = 1440;
        double srcX4 = 0;
        double srcY = 241;
        double srcHeight = 772;

        double dstX = 56.8;
        double dstY = 33.5;
        double dstWidth = 262.4;
        double dstHeight = 447.3;

        CvSeq seq = cvHoughCircles(newGray, circles, CV_HOUGH_GRADIENT, 2.1d, (double)newGray.height()/40, 85d, 65d, 5, 50);

        JavaCV.getPerspectiveTransform(new double[]{srcX1, srcY, srcX2,srcY, srcX3, srcHeight, srcX4, srcHeight}, 
                  new double[]{dstX, dstY, dstWidth, dstY, dstWidth, dstHeight, dstX, dstHeight}, mmat);
        cvWarpPerspective(seq, seq, mmat);


        for(int j=0; j<seq.total(); j++){
            CvPoint3D32f point = new CvPoint3D32f(cvGetSeqElem(seq, j));

            float xyr[] = {point.x(),point.y(),point.z()};
            CvPoint center = new CvPoint(Math.round(xyr[0]), Math.round(xyr[1]));

            int radius = Math.round(xyr[2]);
            cvCircle(gray, center, 3, CvScalar.GREEN, -1, 8, 0);
            cvCircle(gray, center, radius, CvScalar.BLUE, 3, 8, 0);
        }

另外,我想值得一提的是,我使用的是JavaCV,以防方法调用看起来与您习惯的有点不同。谢谢你的帮助。

回答:


你想要做的问题(除了显而易见的opencv不允许你做之外)是半径不能真正正确地扭曲。假设当m是变换矩阵时,xy坐标很容易计算x'=((m00x+m01y+m02)/(m20x+m21y+m22))y'=((m10x+m11y+m12)/(m20x+m21y_m22))。通过变换原始圆的所有点,然后找到x'y'和这些点之间的最大距离(如果扭曲图像中的半径预计覆盖所有这些点,则至少可以修改半径) 顺便说一句,mIJx=m(i,j)*x(只是澄清一下)

结束回答。


<>我写的一切都是根据C++版本,我从来没有使用JavaCV,但是从我可以看到的,它只是一个包装器,调用了本机C++ ++。 CvSeq是一种Sequalance数据结构,其行为类似于链表。 应用程序压碎的断言是

CV_Assert(seq->total > 0 && CV_ELEM_SIZE(seq->flags) == seq->elem_size);
这意味着您的seq实例为空(total是序列中的元素数),或者内部seq标志已损坏

我建议你检查一下你的CvSeq的会员总数,以及cvHoughCircles电话。 所有这些都发生在cvWarpPerspective的实际实现之前(它是实现中的第一行,只将CvSeq转换为cv::Mat)。。因此,这不是扭曲,而是你在这之前所做的。 无论如何,为了了解cvHoughCircles的问题,我们需要更多关于新建Gray和circles的信息

下面是我在javaCV页面()上找到的一个示例

无法工作,因为源mat和目标mat引用相同的数据。 并非OpenCV(以及一般的图像处理)中的所有功能都能工作(因为没有原位算法,或者因为它比其他版本更慢,例如,n*n mat的转置将在原位工作,但是n*m,其中n!=m将更难在原位工作,并且可能会更慢)
您不能假设使用src矩阵作为dst将起作用。

人们正在查看此问题,但没有人提供任何建议。我的要求不会那么难。任何反馈都会非常有帮助。我很想看到测试图像!不久前我问过,我发现这与你的问题有某种联系,你可能会感兴趣。@karlphillip嗨,Karl,是的,我看了你的问题,这有助于我更好地理解这些方法是如何工作的。唯一的问题是,我实际上不需要变换整个图像。。。我只需要找到台球的坐标,如果图像从梯形变成矩形,谢谢你的建议。我一直在反复尝试不同的变换方法,如cvPerspectiveTransform和cvTransform。cvPerspectiveTransform似乎可以将CvSeq作为输入,并且它采用我在代码中创建的3x3转换矩阵(我认为)。我现在遇到的问题是:函数cv::Mat cv::cvarrToMat(const CvArr*,bool,bool,int)中的数组类型未知。我明白你的意思了,你说你需要一个垫子。如果可以的话,我很乐意使用它,但是一旦点被绘制和扭曲,我如何从Mat中提取它们呢?你得到的错误是因为你所拥有的特定CvSeq无法转换为Mat(或iplimage),这意味着你指定的函数中没有一个可以工作,它们期望的是图像而不是x-y半径的数组列表。在发布代码段之后,您希望得到什么?是否要找到圆,对其进行变换,然后绘制变换后的圆?如果是这样,尝试创建一个空白图像,将CVSEQ中的所有X-Y-RADIUS值绘制为CVCLE在空白图像上的填充圆。然后将图像转换为遮罩(填充圆present-1或-0),使用cvWarpPerspective进行转换,然后将其与代码中的灰色图像(cvWarpPerspective之后)组合。顺便说一句,建议在做cvHoughCircles之前对图像进行某种平滑处理,这样可以提高结果。我想要的是在开始的图像中找到圆的坐标,然后只变换坐标。首先扭曲图像,然后在其上做HoughCircles不起作用,因为台球看起来不再像圆了。这应该不会太难,对吧?你想要做的问题(除了显而易见的opencv不允许你做之外)是半径不能真正正确扭曲。假设(我还没有测试过)当m是变换矩阵时,xy坐标很容易计算x'=((m00x+m01y+m02)/(m20x+m21y+m22))y'=((m10x+m11y+m12)/(m20x+m21y_m22))。通过变换原始圆的所有点,然后找到x'y'和这些点之间的最大距离(如果扭曲图像中所需的半径预计覆盖所有这些点,则至少可以修改半径)
CV_Assert(seq->total > 0 && CV_ELEM_SIZE(seq->flags) == seq->elem_size);
IplImage gray = cvCreateImage( cvSize( img.width, img.height ), IPL_DEPTH_8U, 1 );
cvCvtColor( img, gray, CV_RGB2GRAY );
// smooth it, otherwise a lot of false circles may be detected
cvSmooth(gray,gray,CV_GAUSSIAN,9,9,2,2);
CvMemStorage circles = CvMemStorage.create();
CvSeq seq = cvHoughCircles(gray, circles.getPointer(), CV_HOUGH_GRADIENT,
                                                2, img.height/4, 100, 100, 0, 0);
for(int i=0; i<seq.total; i++){
        float xyr[] = cvGetSeqElem(seq,i).getFloatArray(0, 3);
        CvPoint center = new CvPoint(Math.round(xyr[0]), Math.round(xyr[1]));

        int radius = Math.round(xyr[2]);
        cvCircle(img, center.byValue(), 3, CvScalar.GREEN, -1, 8, 0);
        cvCircle(img, center.byValue(), radius, CvScalar.BLUE, 3, 8, 0);
}
cvWarpPerspective(seq, seq, mmat);