Si el artículo es original, no se puede reproducir sin permiso La
dirección del blog del blogger original: https://blog.csdn.net/qq21497936 La
navegación del blog del blogger original: https://blog.csdn.net/qq21497936/article/details / 102478062
La dirección del blog de este artículo: https://blog.csdn.net/qq21497936/article/details/105544972
lectores, el conocimiento es infinito y la mano de obra es pobre, cambie la demanda o encuentre un profesional o investigue usted mismo
Directorio
Probabilidad acumulativa Transformación de línea de Hough
1. El espacio bidimensional de una imagen en línea recta puede representarse mediante dos variables.
Prototipo de probabilidad acumulativa Función de transformación de Hough
Prototipo de función de datos suplementarios
Plantilla de proyecto: número de versión correspondiente v1.38.0
Publicación de blog de referencia
Columna de desarrollo de OpenCV (haga clic en el portal)
Notas de desarrollo de OpenCV (cuarenta y tres): Red Fat Man le toma 8 minutos para obtener una comprensión profunda de la probabilidad acumulativa Transformación de línea de Hough (tanto imágenes como texto + fácil de entender + fuente del programa)
Prólogo
Hombre gordo rojo también viene! ! !
Después de la eliminación de ruido y la detección de bordes, se realiza la extracción de características. Uno de los métodos básicos para identificar gráficos es la transformación de Hough. La transformación de Hough es una tecnología de extracción de características en el procesamiento de imágenes. El artículo anterior explicaba la transformación de línea de Hough En este capítulo, explicaremos la probabilidad acumulativa de transformación de línea de Hough en la transformación de línea de Hough.
Aquí volveré a hablar sobre el principio para profundizar su comprensión. Porque la comprensión de 8 minutos de la transformación de Hough no es suficiente en el artículo anterior. La transformación de Hough es uno de los métodos de detección importantes. Para comparar los efectos de detección.
Manifestación
Transformación de Hough
Resumen
Hough Transform (Transformación Hough) es una tecnología de extracción de características en el procesamiento de imágenes.El proceso de modificación calcula el valor máximo local del resultado acumulativo en un espacio de parámetros para obtener un conjunto que se ajusta a la forma específica como resultado de la Transformación Hough.
La clásica transformación de Hough se usa para detectar líneas rectas en la imagen, luego se extendió al reconocimiento de objetos de formas arbitrarias, principalmente círculos y elipses.
La transformación de Hough usa la transformación entre dos espacios de coordenadas para mapear una curva o una línea recta con la misma forma en un espacio a un punto en otro control de coordenadas para formar un pico, convirtiendo así el problema de detectar cualquier forma en un problema de pico estadístico .
La transformación de Hough en OpenCV se divide en dos tipos, y la transformación de línea se divide en tres tipos, como se muestra a continuación:
Probabilidad acumulativa Transformación de línea de Hough
Resumen
Transformación de línea Hough, puede saber por el nombre que en realidad es para líneas rectas. Obviamente, es un método para encontrar líneas rectas. Aquí prestamos especial atención. Antes de usar la transformación de línea Hough, es necesario preprocesar la imagen: reducción de ruido, detección de bordes , La transformación de línea de Hough solo busca líneas rectas y solo puede reconocer imágenes binarias de borde, por lo que la entrada solo puede ser imágenes binarizadas (canal único de 8 bits).
La transformación de línea de Hough se divide en tres tipos, como se muestra a continuación:
La transformación de líneas intensas encontrará una gran cantidad de líneas, pero algunas líneas son realmente inútiles.
Principio
1. El espacio bidimensional de una imagen en línea recta puede representarse mediante dos variables.
- En el sistema de coordenadas cartesianas: se puede expresar por pendiente de parámetro e intercepción (m, b);
- En el sistema de coordenadas polares (el método adoptado por la transformada de Hough): se puede expresar mediante el parámetro diámetro polar y ángulo polar (r, θ);
La transformación de Hough usa coordenadas polares para representar líneas rectas.
Entonces la expresión de la línea recta es:
La fórmula para r es:
2. En general, para un punto (x0, y0), se puede definir uniformemente por un conjunto de líneas rectas en este punto
rθ = x0 * cosθ + y0 * sinθ
Cada par (rθ, θ) representa una línea recta que pasa por el punto (x0, y0).
3. Para un punto dado (x0, y0), todas las líneas rectas que pasan a través de él en coordenadas polares al diámetro polar y al plano del ángulo polar obtendrán una curva sinusoidal
Por ejemplo, para un punto dado x0 = 8 e y0 = 6, el principio de cálculo es el siguiente:
Puede obtener la siguiente curva:
Solo dibuje ciertas condiciones, como r> 0 y 0 <θ <2π, (nota: 0 significa línea vertical, π / 2 grados significa línea horizontal);
4. Realice las operaciones anteriores en todos los puntos de la imagen para obtener un conjunto de gráficos
Si las curvas obtenidas después de las operaciones anteriores en dos puntos diferentes se cruzan en el plano θ-r, significa que pasan por la misma línea recta.
Por ejemplo, siguiendo el ejemplo anterior, continúe trazando los puntos x1 = 9, y1 = 4 y x2 = 12, y2 = 3 de la siguiente manera:
Estas tres curvas se comparan con puntos ( 0.925, 9.6 ) en el plano , y las coordenadas representan los pares de parámetros θ-r o puntos (x0, y0), (x1, y1) y (x2, y2) en el plano Línea recta, por lo que en realidad está calculando la distancia de cada ángulo de cada punto en el plano. Después de dibujarlo en una curva, si 3 puntos se cruzan, entonces los 3 puntos están en línea recta, como se muestra en la siguiente figura:
(El número de curvas que se cruzan en un punto excede el umbral (el número de puntos en la misma línea recta). Por ejemplo, en el esquema anterior, se supone que 3 puntos pueden formar una línea recta, luego pueden detectar un salto en línea recta)
5. De lo anterior, se puede detectar una línea recta al encontrar el número de curvas que se cruzan en un punto en el plano θ-r.
Cuantas más curvas se crucen en un punto, más líneas rectas representadas por el punto focal de este punto se componen de más puntos. En general, podemos definir cuántas curvas se cruzan en un punto estableciendo el umbral de puntos en una línea recta, de modo que se detecte una línea recta.
Lo anterior es lo que hace la transformación de Hough. Sigue la intersección de la curva correspondiente de cada punto en la imagen. Si el número de curvas que cruzan un punto excede el umbral (el umbral del número de puntos en la misma línea), entonces la intersección puede considerarse El par de parámetros representativos (θ, rθ) es una línea recta en la imagen original.
Prototipo de probabilidad acumulativa Función de transformación de Hough
void HoughLinesP( InputArray image,
OutputArray lines,
double rho,
double theta,
int threshold,
double minLineLength = 0,
double maxLineGap = 0 );
- Parámetro 1: imagen de tipo InputArray, imagen de origen de 8 bits, imagen binaria de un solo canal. Puede cargar cualquier imagen original y modificarla a este formato mediante la función, luego completarla aquí;
- Parámetro dos: las líneas de tipo OutputArray, después de llamar a la función HoughLines, almacenan el vector de salida de las líneas detectadas por la transformación Hough. Cada línea consiste en un vector de dos elementos (r, θ), r representa la distancia desde el origen de las coordenadas, θ es el ángulo de rotación de la línea radianes (0 representa una línea vertical, π / 2 grados representa una línea horizontal);
- Parámetro 3: doble tipo rho, rho es la distancia de la línea recta, si es 1 píxel, luego detecta la línea recta de longitud 1-> 2-> 3, si es 2, entonces 2-> 4-> 6 ignora 1 y 3 Demasiado
- Parámetro cuatro: theta de tipo doble, theta es radianes, incluso si todas son líneas, entonces la precisión en radianes entre líneas y líneas, si un punto de 360 grados, radianes es π, significa que comienza desde 0 °, cada π radianes (180 °, detectar una línea) ;
- Parámetro cinco: umbral de tipo int , el parámetro umbral del plano de acumulación, es decir, el valor que debe alcanzar en el plano de acumulación al identificar una parte como una línea recta en la figura. Mayor que el valor umbral de umbral de segmento de línea puede ser detectado por el resultado y retorno a la;
- Parámetro 6: minLineLength de tipo doble , el valor predeterminado es 0 , lo que significa que la longitud del segmento de línea más bajo, el segmento de línea más corto que este parámetro de configuración no se puede detectar;
- Parámetro 7: maxLineGap de tipo double , el valor predeterminado es 0 , la distancia máxima permitida para conectar puntos en la misma línea;
Prototipo de función de datos suplementarios
cvRound():返回跟参数最接近的整数值,即四舍五入;
cvFloor():返回不大于参数的最大整数值,即向下取整;
cvCeil():返回不小于参数的最小整数值,即向上取整;
Código fuente de demostración
void OpenCVManager::testHoughLinesP()
{
QString fileName1 =
"E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/16.jpg";
cv::Mat srcMat = cv::imread(fileName1.toStdString());
int width = 400;
int height = 300;
cv::resize(srcMat, srcMat, cv::Size(width, height));
cv::Mat colorMat = srcMat.clone();
cv::String windowName = _windowTitle.toStdString();
cvui::init(windowName);
cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2, srcMat.rows * 3),
srcMat.type());
cv::cvtColor(srcMat, srcMat, CV_BGR2GRAY);
int threshold1 = 200;
int threshold2 = 100;
int apertureSize = 1;
int rh0 = 1; // 默认1像素
int theta = 1; // 默认1°
int threshold = 100; // 默认检测到同一直线的100个点
int minLineLength = 50; // 检测线的最小长度
int maxLineGap = 10; // 同一条线点与点的最大距离
while(true)
{
qDebug() << __FILE__ << __LINE__;
windowMat = cv::Scalar(0, 0, 0);
cv::Mat mat;
cv::Mat dstMat;
cv::Mat grayMat;
// 转换为灰度图像
// 原图先copy到左边
cv::Mat leftMat = windowMat(cv::Range(0, srcMat.rows),
cv::Range(0, srcMat.cols));
cv::cvtColor(srcMat, grayMat, CV_GRAY2BGR);
cv::addWeighted(leftMat, 0.0f, grayMat, 1.0f, 0.0f, leftMat);
{
cvui::printf(windowMat,
width * 1 + 100,
height * 0 + 20,
"threshold1");
cvui::trackbar(windowMat,
width * 1 + 100,
height * 0 + 50,
200,
&threshold1,
0,
255);
cvui::printf(windowMat,
width * 1 + 100,
height * 0 + 100, "threshold2");
cvui::trackbar(windowMat,
width * 1 + 100,
height * 0 + 130,
200,
&threshold2,
0,
255);
cv::Canny(srcMat, dstMat, threshold1, threshold2, apertureSize * 2 + 1);
// copy
mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
cv::Range(srcMat.cols * 0, srcMat.cols * 1));
cv::cvtColor(dstMat, grayMat, CV_GRAY2BGR);
cv::addWeighted(mat, 0.0f, grayMat, 1.0f, 0.0f, mat);
cvui::printf(windowMat,
width * 1 + 100,
height * 1 + 20 - 120,
"rho / 100");
cvui::trackbar(windowMat,
width * 1 + 100,
height * 1 + 50 - 120,
200,
&rh0,
1,
1000);
cvui::printf(windowMat,
width * 1 + 100,
height * 1 + 100 - 120,
"theta = value / 2");
cvui::trackbar(windowMat,
width * 1 + 100,
height * 1 + 130 - 120,
200,
&theta,
1,
720);
cvui::printf(windowMat,
width * 1 + 100,
height * 1 + 180 - 120,
"min points");
cvui::trackbar(windowMat,
width * 1 + 100,
height * 1 + 210 - 120,
200,
&threshold,
2,
300);
cvui::printf(windowMat,
width * 1 + 100,
height * 1 + 260 - 120,
"minLineLength = value / 10");
cvui::trackbar(windowMat,
width * 1 + 100,
height * 1 + 290 - 120,
200,
&minLineLength,
0,
1000);
cvui::printf(windowMat,
width * 1 + 100,
height * 1 + 340 - 120,
"maxLineGap = value / 10");
cvui::trackbar(windowMat,
width * 1 + 100,
height * 1 + 370 - 120,
200,
&maxLineGap,
0,
1000);
// 边缘检测后,进行霍夫线检测
// 使用霍夫线变化检测所有角度范围内的直线
std::vector<cv::Vec2f> lines;
cv::HoughLines(dstMat, // 输入8位
lines, // 输出线 std::vector<std::Vec2f>
rh0 / 100.0f, // 初步像素精度
theta / 720.0 * CV_PI, // 初步偏移角度精度
threshold, // 必须达到的点的数量
0, // 标准霍夫变换,为0
0, // 标准霍夫变换,为0
0, // 检测角度范围最小为0
CV_PI); // 检测角度范围最大为π,即360°
// 在图中绘制出每条线段
dstMat = colorMat.clone();
qDebug() << __FILE__ << __LINE__ << lines.size();
for(int index = 0; index < lines.size(); index++)
{
float rho = lines[index][0];
float theta = lines[index][1];
cv::Point pt1;
cv::Point pt2;
double a = cos(theta);
double b = sin(theta);
double x0 = a * rho;
double y0 = b * rho;
// 计算出点的坐标
pt1.x = cvRound(x0 + 1000 * (-b));
pt1.y = cvRound(y0 + 1000 * (a));
pt2.x = cvRound(x0 - 1000 * (-b));
pt2.y = cvRound(y0 - 1000 * (a));
// 画线
cv::line(dstMat, pt1, pt2, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
}
// copy
mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
cv::Range(srcMat.cols * 0, srcMat.cols * 1));
cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
// 使用概率霍夫线变化检测所有长度范围内的直线
cv::Canny(srcMat, dstMat, threshold1, threshold2, apertureSize * 2 + 1);
std::vector<cv::Vec4i> lines2;
cv::HoughLinesP(dstMat, // 输入8位
lines2, // 输出线 std::vector<std::Vec4i>
rh0/100.0f, // 初步像素精度
theta / 720.0 * CV_PI, // 初步偏移角度精度
threshold, // 必须达到的点的数量
minLineLength / 10.0f, // 检测线的最小长度
maxLineGap / 10.0f); // 检测线的最大距离
// 在图中绘制出每条线段
dstMat = colorMat.clone();
for(int index = 0; index < lines.size(); index++)
{
// 画线
cv::Vec4i line = lines2[index];
cv::line(dstMat,
cv::Point(line[0], line[1]),
cv::Point(line[2], line[3]),
cv::Scalar(0, 0, 255),
1,
cv::LINE_AA);
}
// copy
mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
cv::Range(srcMat.cols * 1, srcMat.cols * 2));
cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
}
// 更新
cvui::update();
// 显示
cv::imshow(windowName, windowMat);
// esc键退出
if(cv::waitKey(25) == 27)
{
break;
}
}
}
Plantilla de proyecto: número de versión correspondiente v1.38.0
Número de versión correspondiente v1.38.0
Publicación de blog de referencia
https://blog.csdn.net/shenziheng1/article/details/75307410
La dirección del blog del blogger original: https://blog.csdn.net/qq21497936 La
navegación del blog del blogger original: https://blog.csdn.net/qq21497936/article/details/102478062
La dirección del blog de este artículo: https: // blog .csdn.net / qq21497936 / article / details / 105544972