opencv2.4.9 & VS2013環(huán)境
一個簡單的問題:
在圖中找出兩條直線锋爪,并找到兩條直線交點位置丙曙。
1.jpg
思路:
讀圖,二值化其骄,簡單腐蝕亏镰,之后直線在原圖中比較明顯,所以考慮直接用霍夫變換尋找直線拯爽。
霍夫直線檢測可能會檢測出多條重疊直線索抓,利用上下兩部分直線斜率相反篩選一下,選出兩條直線。
3)兩條直線求交點逼肯,變?yōu)榻舛淮畏匠虇栴}耸黑。
4)畫出結果
實現(xiàn):
1)調用opencv中的HoughLinesP函數(shù):
void HoughLinesP( InputArray image, OutputArray lines,
double rho, double theta, int threshold,
double minLineLength=0, double maxLineGap=0 );
image為輸入圖像,要求是8位單通道圖像
lines為輸出的直線向量篮幢,每條線用4個元素表示大刊,即直線的兩個端點的4個坐標值
rho和theta分別為距離和角度的分辨率
threshold為閾值,即步驟3中的閾值
minLineLength為最小直線長度三椿,在步驟5中要用到缺菌,即如果小于該值,則不被認為是一條直線
maxLineGap為最大直線間隙赋续,在步驟4中要用到男翰,即如果有兩條線段是在一條直線上,但它們之間因為有間隙纽乱,所以被認為是兩個線段蛾绎,如果這個間隙大于該值,則被認為是兩條線段鸦列,否則是一條租冠。
2)檢測出的直線為Vec4i類型,一共四位數(shù)薯嗤。分別代表直線上的(x1,y1,x2,y2)顽爹,求出每條直線寫了,Ka * kB<0即代表兩條直線鞋履相反
3)利用四個點坐標解方程骆姐,返回point2f類型的一個點
4)利用Line()以及circle()函數(shù)畫出圖像
上代碼:
/*Copyright:ZhenYM @ Harbin Institute of Technology; Nov,29, 2017*/
# include <opencv2/opencv.hpp>
# include <iostream>
using namespace cv;
using namespace std;
/*函數(shù)功能:求兩條直線交點*/
/*輸入:兩條Vec4i類型直線*/
/*返回:Point2f類型的點*/
Point2f getCrossPoint(Vec4i LineA, Vec4i LineB)
{
double ka, kb;
ka = (double)(LineA[3] - LineA[1]) / (double)(LineA[2] - LineA[0]); //求出LineA斜率
kb = (double)(LineB[3] - LineB[1]) / (double)(LineB[2] - LineB[0]); //求出LineB斜率
Point2f crossPoint;
crossPoint.x = (ka*LineA[0] - LineA[1] - kb*LineB[0] + LineB[1]) / (ka - kb);
crossPoint.y = (ka*kb*(LineA[0] - LineB[0]) + ka*LineB[1] - kb*LineA[1]) / (ka - kb);
return crossPoint;
}
int main(){
Mat src, grayImg, binImg, result;
src = imread("./1.jpg");
//imshow("srcimage", src);
//waitKey(30);
/*檢查圖像是否載入*/
if (src.empty()) {
printf("Error Loading Image...\n");
return -1;
}
/*轉為灰度圖*/
if (src.channels() == 3){
cvtColor(src, grayImg, CV_BGR2GRAY);
}
else if (src.channels() == 2){
grayImg = src.clone();
}
/*二值化*/
threshold(grayImg, binImg, 100, 255, THRESH_BINARY);
//adaptiveThreshold(grayImg, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
//imshow("binary image", binImg);
//waitKey(100);
/*腐蝕*/
Mat element = getStructuringElement(MORPH_RECT, Size(2, 1));
Mat erodeImg;
erode(binImg, erodeImg, element);
//imshow("erode", erodeImg);
//waitKey(100);
/*霍夫直線檢測*/
vector<Vec4i> Lines;
HoughLinesP(erodeImg, Lines, 1, CV_PI / 360, 200, 100, 10);
Vec4i LineStand = Lines[0];
Vec4i LineAnother;
double ka = (double)(LineStand[1] - LineStand[3]) / (double)(LineStand[0] - LineStand[2]);
double kb;
for (int i = 1; i < Lines.size(); i++)
{
double ki = (double)(Lines[i][1] - Lines[i][3]) / (double)(Lines[i][0] - Lines[i][2]);
if (ki*ka < 0)
{
LineAnother = Lines[i];
kb = ki;
}
}
/*畫出兩條直線*/
result = src.clone();
line(result, Point(LineStand[0], LineStand[1]), Point(LineStand[2], LineStand[3]), Scalar(0, 255, 0), 2, 8);
line(result, Point(LineAnother[0], LineAnother[1]), Point(LineAnother[2], LineAnother[3]), Scalar(0, 0, 255), 2, 8);
cout << "直線A過點(" << LineStand[0] << "," << LineStand[1] << ")以及點(" << LineStand[2]<<"镜粤,"<<LineStand[3] << ");斜率為:" << ka << endl;
cout << "直線B過點(" << LineAnother[0] << "玻褪," << LineAnother[1] << ")以及點(" << LineAnother[2] << "肉渴," << LineAnother[3] << ");斜率為:" << kb << endl;
/*求交點并畫點保存带射,result.jpg存儲在工程目錄下*/
Point2f crossPoint;
crossPoint = getCrossPoint(LineStand, LineAnother);
circle(result, crossPoint, 6, Scalar(255, 0, 0));
imwrite("./result.jpg", result);
cout << "Copyrigth@zym" << endl;
cout << "交點坐標為:" << crossPoint << endl;
imshow("result", result);
waitKey(100);
system("pause");
return 0;
}
運行結果:
result.jpg
consolew.png