OpenCV 概率 Hough 线变换使用 C++ 和 Python 给出不同的结果?
OpenCV Probabilistic Hough Line Transform giving different results with C++ and Python?
我正在使用 OpenCV 开发一个项目,Python 在项目的某些部分使用概率霍夫线变换函数“HoughLinesP”。我的代码工作得很好,没有问题。然后我想到将相同的代码转换为C++。
将代码转换为 C++ 后,输出与 Python 代码不同。经过长时间的调试,我发现其他一切工作正常,但“HoughLinesP”函数在 C++ 的情况下给出不同的输出。该函数在两种语言中的输入相同,参数值也相同,但输出不同。
有人可以向我解释为什么会发生这种情况以及任何可能的修复方法吗?
另外,我检查了两种语言的OpenCV版本,是一样的:
4.5.0 dev
此外,我尝试使用传递给 C++ 代码的值,但我无法获得类似的结果。
输入边缘图像:
Python HoughLinesP() 输出:
C++ HoughLinesP() 输出:
以下是每种语言的代码:
Python:
Lines = cv2.HoughLinesP(EdgeImage, 1, np.pi / 180, 50, 10, 15)
C++:
std::vector<cv::Vec4i> Lines;
cv::HoughLinesP(EdgeImage, Lines, 1, CV_PI / 180, 50, 10, 15);
如果有人能提出建议,那将是一个很大的帮助。
解释和修正
问题的出现是因为在 Python 版本中您没有设置您认为正在设置的参数。与在 Python 接口中修改参数列表的一些其他函数相比,HoughLinesP
不仅 return 行而且仍然采用参数 lines
作为线路输出。您可以在 HoughLinesP
:
的帮助中看到
import cv2
help(cv2.HoughLinesP)
这给了你(我的省略号):
Help on built-in function HoughLinesP:
HoughLinesP(...)
HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]]) -> lines
. @brief Finds line segments in a binary image using the probabilistic Hough transform.
.
...
. @param lines Output vector of lines. Each line is represented by a 4-element vector
. \f$(x_1, y_1, x_2, y_2)\f$ , where \f$(x_1,y_1)\f$ and \f$(x_2, y_2)\f$ are the ending points of each detected
. line segment.
...
所以基本上,在您的 python 示例中,您将 10
作为 lines
而不是 minLineLength
传递。要解决此问题,您可以将空数组作为 lines
传递,也可以将参数作为关键字参数传递:
Lines = cv2.HoughLinesP(EdgeImage, rho=1, theta=np.pi/180,
threshold=50, minLineLength=10, maxLineGap=15)
这样做应该会使您的 Python 版本的输出与 C++ 版本的输出相匹配。
或者,如果您对 Python 版本的结果满意,则必须省略参数 lines
(即仅将 minLineLength
设置为 15 并使用默认值0 maxLineGap
[see docs]):
std::vector<cv::Vec4i> Lines;
cv::HoughLinesP(EdgeImage, Lines, 1, CV_PI / 180, 50, 15);
这应该会重现您的 Python 版本。
例子
使用 openCV documentation of HoughLinesP
中列出的示例,您可以看到这解决了问题。
C++ 版本
(取自上面列出的 openCV 文档并改为保存图像。)
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src, dst, color_dst;
if( argc != 3 || !(src=imread(argv[1], 0)).data)
return -1;
Canny( src, dst, 50, 200, 3 );
cvtColor( dst, color_dst, COLOR_GRAY2BGR );
vector<Vec4i> lines;
HoughLinesP( dst, lines, 1, CV_PI/180, 80, 30, 10 );
for( size_t i = 0; i < lines.size(); i++ )
{
line( color_dst, Point(lines[i][0], lines[i][1]),
Point( lines[i][2], lines[i][3]), Scalar(0,0,255), 3, 8 );
}
imwrite( argv[2], color_dst );
return 0;
}
如果你在文档中提供的示例图片上编译它并运行它,你会得到以下结果:
Python 版本不正确
(基本上就是没有lines参数的C++翻译版本)
import argparse
import cv2
import numpy as np
parser = argparse.ArgumentParser()
parser.add_argument("input_file", type=str)
parser.add_argument("output_file", type=str)
args = parser.parse_args()
src = cv2.imread(args.input_file, 0)
dst = cv2.Canny(src, 50., 200., 3)
color_dst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR)
lines = cv2.HoughLinesP(dst, 1., np.pi/180., 80, 30, 10.)
for this_line in lines:
cv2.line(color_dst,
(this_line[0][0], this_line[0][1]),
(this_line[0][2], this_line[0][3]),
[0, 0, 255], 3, 8)
cv2.imwrite(args.output_file, color_dst)
运行 这给出了以下(不同的)结果:
更正 python 版本
(通过传递关键字参数来修复)
import argparse
import cv2
import numpy as np
parser = argparse.ArgumentParser()
parser.add_argument("input_file", type=str)
parser.add_argument("output_file", type=str)
args = parser.parse_args()
src = cv2.imread(args.input_file, 0)
dst = cv2.Canny(src, 50., 200., 3)
color_dst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR)
lines = cv2.HoughLinesP(dst, rho=1., theta=np.pi/180.,
threshold=80, minLineLength=30, maxLineGap=10.)
for this_line in lines:
cv2.line(color_dst,
(this_line[0][0], this_line[0][1]),
(this_line[0][2], this_line[0][3]),
[0, 0, 255], 3, 8)
cv2.imwrite(args.output_file, color_dst)
这给出了正确的结果(即与 C++ 版本相同的结果):
我正在使用 OpenCV 开发一个项目,Python 在项目的某些部分使用概率霍夫线变换函数“HoughLinesP”。我的代码工作得很好,没有问题。然后我想到将相同的代码转换为C++。
将代码转换为 C++ 后,输出与 Python 代码不同。经过长时间的调试,我发现其他一切工作正常,但“HoughLinesP”函数在 C++ 的情况下给出不同的输出。该函数在两种语言中的输入相同,参数值也相同,但输出不同。
有人可以向我解释为什么会发生这种情况以及任何可能的修复方法吗?
另外,我检查了两种语言的OpenCV版本,是一样的:
4.5.0 dev
此外,我尝试使用传递给 C++ 代码的值,但我无法获得类似的结果。
输入边缘图像:
Python HoughLinesP() 输出:
C++ HoughLinesP() 输出:
以下是每种语言的代码: Python:
Lines = cv2.HoughLinesP(EdgeImage, 1, np.pi / 180, 50, 10, 15)
C++:
std::vector<cv::Vec4i> Lines;
cv::HoughLinesP(EdgeImage, Lines, 1, CV_PI / 180, 50, 10, 15);
如果有人能提出建议,那将是一个很大的帮助。
解释和修正
问题的出现是因为在 Python 版本中您没有设置您认为正在设置的参数。与在 Python 接口中修改参数列表的一些其他函数相比,HoughLinesP
不仅 return 行而且仍然采用参数 lines
作为线路输出。您可以在 HoughLinesP
:
import cv2
help(cv2.HoughLinesP)
这给了你(我的省略号):
Help on built-in function HoughLinesP:
HoughLinesP(...)
HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]]) -> lines
. @brief Finds line segments in a binary image using the probabilistic Hough transform.
.
...
. @param lines Output vector of lines. Each line is represented by a 4-element vector
. \f$(x_1, y_1, x_2, y_2)\f$ , where \f$(x_1,y_1)\f$ and \f$(x_2, y_2)\f$ are the ending points of each detected
. line segment.
...
所以基本上,在您的 python 示例中,您将 10
作为 lines
而不是 minLineLength
传递。要解决此问题,您可以将空数组作为 lines
传递,也可以将参数作为关键字参数传递:
Lines = cv2.HoughLinesP(EdgeImage, rho=1, theta=np.pi/180,
threshold=50, minLineLength=10, maxLineGap=15)
这样做应该会使您的 Python 版本的输出与 C++ 版本的输出相匹配。
或者,如果您对 Python 版本的结果满意,则必须省略参数 lines
(即仅将 minLineLength
设置为 15 并使用默认值0 maxLineGap
[see docs]):
std::vector<cv::Vec4i> Lines;
cv::HoughLinesP(EdgeImage, Lines, 1, CV_PI / 180, 50, 15);
这应该会重现您的 Python 版本。
例子
使用 openCV documentation of HoughLinesP
中列出的示例,您可以看到这解决了问题。
C++ 版本
(取自上面列出的 openCV 文档并改为保存图像。)
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src, dst, color_dst;
if( argc != 3 || !(src=imread(argv[1], 0)).data)
return -1;
Canny( src, dst, 50, 200, 3 );
cvtColor( dst, color_dst, COLOR_GRAY2BGR );
vector<Vec4i> lines;
HoughLinesP( dst, lines, 1, CV_PI/180, 80, 30, 10 );
for( size_t i = 0; i < lines.size(); i++ )
{
line( color_dst, Point(lines[i][0], lines[i][1]),
Point( lines[i][2], lines[i][3]), Scalar(0,0,255), 3, 8 );
}
imwrite( argv[2], color_dst );
return 0;
}
如果你在文档中提供的示例图片上编译它并运行它,你会得到以下结果:
Python 版本不正确
(基本上就是没有lines参数的C++翻译版本)
import argparse
import cv2
import numpy as np
parser = argparse.ArgumentParser()
parser.add_argument("input_file", type=str)
parser.add_argument("output_file", type=str)
args = parser.parse_args()
src = cv2.imread(args.input_file, 0)
dst = cv2.Canny(src, 50., 200., 3)
color_dst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR)
lines = cv2.HoughLinesP(dst, 1., np.pi/180., 80, 30, 10.)
for this_line in lines:
cv2.line(color_dst,
(this_line[0][0], this_line[0][1]),
(this_line[0][2], this_line[0][3]),
[0, 0, 255], 3, 8)
cv2.imwrite(args.output_file, color_dst)
运行 这给出了以下(不同的)结果:
更正 python 版本
(通过传递关键字参数来修复)
import argparse
import cv2
import numpy as np
parser = argparse.ArgumentParser()
parser.add_argument("input_file", type=str)
parser.add_argument("output_file", type=str)
args = parser.parse_args()
src = cv2.imread(args.input_file, 0)
dst = cv2.Canny(src, 50., 200., 3)
color_dst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR)
lines = cv2.HoughLinesP(dst, rho=1., theta=np.pi/180.,
threshold=80, minLineLength=30, maxLineGap=10.)
for this_line in lines:
cv2.line(color_dst,
(this_line[0][0], this_line[0][1]),
(this_line[0][2], this_line[0][3]),
[0, 0, 255], 3, 8)
cv2.imwrite(args.output_file, color_dst)
这给出了正确的结果(即与 C++ 版本相同的结果):