上下文:
此lecture中的第8页说,OpenCV HoughLines函数返回N x 2的行参数 rho 和 theta 数组。存储在名为 lines 的数组中。
然后为了从这些角度实际创建线,我们有一些公式,后来我们使用了 line 函数。公式在下面的代码中进行了解释。
代码:
//Assuming we start our program with the Input Image as shown below.
//This array will be used for storing rho and theta as N x 2 array
vector<Vec2f> lines;
//The input bw_roi is a canny image with detected edges
HoughLines(bw_roi, lines, 1, CV_PI/180, 70, 0, 0); '
//These formulae below do the line estimation based on rho and theta
for( size_t i = 0; i < lines.size(); i++ )
{
float rho = lines[i][0], theta = lines[i][1];
Point2d pt1, pt2;
double m;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
//When we use 1000 below we get Observation 1 output.
//But if we use 200, we get Observation 2 output.
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
//This line function is independent of HoughLines function
//and is used for drawing any type of line in OpenCV
line(frame, pt1, pt2, Scalar(0,0,255), 3, LINE_AA);
}
输入图像:
观察1:
观察2:
问题:
在上面显示的代码中,如果我们使用数字乘以a,-a,b和-b,则会得到不同长度的行。当我乘以200而不是1000时获得观察值2(得出观察值1)。
有关更多信息,请参见上面显示的代码的第18和19行中的注释。
问题:
当我们从HoughLines输出中绘制线条时,如何控制线条的起点和终点?
例如,我希望观察2中的右车道(红线从左上角指向右下角)从屏幕的右下角开始并指向屏幕的左上角(例如左车道)。
答案 0 :(得分:2)
给予
import lombok.val;
import org.opencv.core.*;
import org.springframework.core.io.ClassPathResource;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import static javax.imageio.ImageIO.read;
import static javax.imageio.ImageIO.write;
import static javax.swing.SwingUtilities.invokeAndWait;
import static org.opencv.core.CvType.CV_32FC1;
import static org.opencv.highgui.HighGui.imshow;
import static org.opencv.highgui.HighGui.waitKey;
import static org.opencv.imgcodecs.Imgcodecs.CV_LOAD_IMAGE_UNCHANGED;
import static org.opencv.imgcodecs.Imgcodecs.imdecode;
import static org.opencv.imgproc.Imgproc.*;
public class TemplateMatcher
{
static
{
// loadNativeOpenCVLibrary();
}
private static final int MATCH_METHOD = TM_SQDIFF_NORMED;
private static Mat BufferedImage2Mat(BufferedImage image) throws IOException
{
try (val byteArrayOutputStream = new ByteArrayOutputStream())
{
write(image, "jpg", byteArrayOutputStream);
byteArrayOutputStream.flush();
val matOfByte = new MatOfByte(byteArrayOutputStream.toByteArray());
return imdecode(matOfByte, CV_LOAD_IMAGE_UNCHANGED);
}
}
public static Point performTemplateMatching(BufferedImage bigImage, BufferedImage templateImage,
double detectionThreshold, boolean showMatch) throws IOException
{
val image = BufferedImage2Mat(bigImage);
val template = BufferedImage2Mat(templateImage);
// Create the result matrix
val result_cols = image.cols() - template.cols() + 1;
val result_rows = image.rows() - template.rows() + 1;
val result = new Mat(result_rows, result_cols, CV_32FC1);
// Do the matching
matchTemplate(image, template, result, MATCH_METHOD);
// Localize the best match
val minMaxLocResult = Core.minMaxLoc(result);
// / Show me what you got
val matchedLocation = minMaxLocResult.minLoc;
rectangle(image, matchedLocation, new Point(matchedLocation.x + template.cols(),
matchedLocation.y + template.rows()), new Scalar(0, 255, 0));
if (showMatch)
{
try
{
invokeAndWait(() -> imshow("Image Search", image));
} catch (InterruptedException | InvocationTargetException exception)
{
exception.printStackTrace();
}
waitKey();
}
// Determine whether this sub image has been found
val minVal = minMaxLocResult.minVal;
if (minVal < detectionThreshold)
{
return minMaxLocResult.maxLoc;
}
return null;
}
public static BufferedImage getBufferedImage(String classpathFile) throws IOException
{
val classPathResource = new ClassPathResource(classpathFile);
val filePath = classPathResource.getFile();
return read(filePath);
}
}
您可以为data(){
cats:[],
...
},
beforeMount(){
axios.get(`${process.env.KITTY_URL}/api/v1/cats/`)
.then(response => {
self.cats = response.data.results; <----What should this be?
})
.catch(error => console.log(error));
},
mounted () {
console.log(this.cats);
}
定义的直线上的所有点编写公式,
a = cos(theta)
b = sin(theta)
x0 = a * rho
y0 = b * rho
其中(rho, theta)
是距参考点的距离(与通过原点的垂直线相交)。
在您的情况下,您已经用x = x0 - c * b
y = y0 + c * a
和c
对其进行了评估,得到了两个要点。
您可以将其重写为
c = 1000
然后使用替代计算水平和垂直截距:
c = -1000
或
c = (x0 - x) / b
c = (y - y0) / a
注意::请注意正确处理x = x0 - ((y - y0) / a) * b
或y = y0 + ((x0 - x) / b) * a
为0的情况。
假设您有一个800x600的图片(使数字保持简单)。我们可以将图像的底部边缘定义为a
行。使用上面的公式计算b
的值,您的行将其截取。
y = 599
)中,那就是您的起点。x
)处,则找到第0 <= x < 800
行的截距作为起点。x < 0
),则找到第x = 0
行的截距作为起点。然后使用类似的技术找到能够画线的第二点。