第十七課 霍夫變換 直線
1.霍夫直線變換介紹
Hough Line Transform用來做直線檢測
前提條件-完成邊緣檢測
平面空間到極座標空間轉換
對於一條直線上的所有點來說,變換到極座標中,從0~360空間,可以得到r的大小,屬於同一條直線
上的點在極座標空間上(r,θ)必然在一個點上有最強的信號出現,根據此反算到平面座標上就可以
得到直線上個點的像素座標,從而得到直線。
2.相關API學習
標準的霍夫變換cv::HoughLines從平面座標轉換到霍夫空間
一般爲有經驗的開發者使用,需要自己反變換到平面空間
HoughLines(
inputArray src,//輸入8bit的灰度圖像
outputArray lines,//用輸出的極座標來表示直線
double rho,//生成極座標時候的像素掃描步長
double theta,//生成極座標是的角步長,一半取值CV_P1/180
int threshold,//閾值,只有獲得足夠交點的極座標點纔會被看成直線
double srn=0,//是否應用多尺度的霍夫變換,如果不是設置爲零表示經典的霍夫變換
double stn=0,//是否應用多尺度的霍夫變換,如果不是設置爲零表示經典的霍夫變換
double min_theta=0,//表示掃描範圍在0到180之間,默認即可
double max_theta=CV_P1//)
霍夫變換直線概率cv::HoughLinesP最終輸出的是直線的兩個點
HoughLinesP(
inputArray src,//輸入8bit的灰度圖像
outputArray lines,//用輸出的極座標來表示直線
double rho,//生成極座標時候的像素掃描步長
double theta,//生成極座標是的角步長,一半取值CV_P1/180
int threshold,//閾值,只有獲得足夠交點的極座標點纔會被看成直線
double minLIneLength=0,//最小直線長度
double maxLineGap//最大間隔)
3.代碼演示
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char**argv)
{
Mat src, dst;
src = imread("H:/pictures/xingtai.png");
if (!src.data)
{
cout << "could not load image.." << endl;
return -1;
}
char input_title[] = "input image";
char output_title[] = "output image";
namedWindow(input_title, CV_WINDOW_AUTOSIZE);
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
imshow(input_title, src);
Mat gray_src,edge_src;
cvtColor(src, gray_src, CV_BGR2GRAY);
Canny(gray_src, edge_src, 150, 200);
cvtColor(edge_src, dst,CV_GRAY2BGR);
imshow("edge image", edge_src);
vector<Vec4f> plines;
HoughLinesP(edge_src, plines, 1, CV_PI / 180.0, 10, 0, 10);
Scalar color = Scalar(0, 255, 255);
for (size_t i = 0; i < plines.size();i++)
{
Vec4f hline = plines[i];
line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);
}
imshow(output_title, dst);
waitKey(0);
return 0;
}
第十八課 霍夫圓檢測
1.霍夫圓檢測原理
從平面座標到極座標轉換爲三個參數,C(x0,y0,r)其中x0,y0爲圓心
假設平面座標的任意一個圓上的點轉換到極座標中:C(x0,y0,r)處有最大值,霍夫變換正是用這個原理
進行圓檢測
2.相關API
霍夫圓檢測對噪聲比較敏感,要先對圖像進行中值濾波
基於效率的考慮OpenCV中霍夫圓檢測是基於圖像梯度的實現,分爲兩步:
檢測邊緣,發現可能的圓心
基於第一步的基礎從候選圓心上計算最佳半徑
一般爲有經驗的開發者使用,需要自己反變換到平面空間
HoughCircles(
inputArray src,//輸入8bit的單通道灰度圖像
outputArray circles,//輸出結果,發現圓信息
int method,//方法-HOUGH_GRADIENT
double dp,//dp=1
double mindist,//10 最短距離,可以分辨兩個圓的,否則認爲是同心圓
double param1,//canny edge detection low threshold
double param2,//中心點累加器閾值-候選圓心
int minradius,//最小半徑
int maxradius//最大半徑)
3.代碼演示
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("H:/pictures/round.png");
if (!src.data) {
printf("could not load image...\n");
return -1;
}
char INPUT_TITLE[] = "input image";
char OUTPUT_TITLE[] = "hough circle demo";
namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
imshow(INPUT_TITLE, src);
// 中值濾波
Mat moutput;
medianBlur(src, moutput, 3);
cvtColor(moutput, moutput, CV_BGR2GRAY);
// 霍夫圓檢測
vector<Vec3f> pcircles;
HoughCircles(moutput, pcircles, CV_HOUGH_GRADIENT, 1, 10, 100, 38, 5, 200);
src.copyTo(dst);
for (size_t i = 0; i < pcircles.size(); i++) {
Vec3f cc = pcircles[i];
circle(dst, Point(cc[0], cc[1]), cc[2], Scalar(0, 0, 255), 2, LINE_AA);
circle(dst, Point(cc[0], cc[1]), 2, Scalar(198, 23, 155), 2, LINE_AA);
}
imshow(OUTPUT_TITLE, dst);
waitKey(0);
return 0;
}