转载请注明本文出自SilenceDut的CSDN博客(http://blog.csdn.net/ls5222325/article/details/46441693),请尊重他人的辛勤劳动成果,谢谢!
最近实现了利用OpenCV在Android平台上通过摄像头拍摄道路图像提取道路线(两条直线的方程)并得到道路的中心线位置,反馈出道路信息和摄像头当前相对道路的信息可用于小车循迹,四旋翼飞行器循迹等。在这个过程中遇到了很多坑,又一步步的爬出,所以记录下以便以后回顾也希望能帮到需要的人。
之前也看过很多关于道路循迹的文章,但只是通过调用Canny等取边缘算子得到道路的边缘然后进行Hough变换得到边缘的直线,但存在的问题是得到的边缘直线有很多条,而且只是显示出直线,后续无法做任何事情,因为得到道路线的目的是为了后续的循迹,所以这种做法的没有太大的意义。先上张效果图。
!
实现
首先进行OpenCV的配置,配置的过程看这里http://blog.csdn.net/nailperry/article/details/42834413,写的很详细了,免Cygwin的。
具体的主要实现部分代码如下:
public class CannySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable{
private static final String TAG = "CannySurfaceView::SurfaceView";
private SurfaceHolder mHolder;
private VideoCapture mCamera;
private Mat rgbMat;
private Mat mShow;
private Mat lines ;
private List<Line> mLines = new ArrayList<Line>();
private Line[] twoLines = new Line[2];
public CannySurfaceView(Context context) {
super(context);
mHolder = getHolder();
mHolder.addCallback(this);
}
public boolean openCamera() {
Log.i(TAG, "openCamera");
synchronized (this) {
releaseCamera();
mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID);
if (!mCamera.isOpened()) {
mCamera.release();
mCamera = null;
Log.e(TAG, "Failed to open native camera");
return false;
}
}
return true;
}
public void releaseCamera() {
Log.i(TAG, "releaseCamera");
synchronized (this) {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
}
public void setupCamera(int width, int height) {
Log.i(TAG, "setupCamera("+width+", "+height+")");
if (mCamera != null && mCamera.isOpened()) {
List<Size> sizes = mCamera.getSupportedPreviewSizes();
int mFrameWidth = width;
int mFrameHeight = height;
// selecting optimal camera preview size
{
double minDiff = Double.MA