【调试笔记】ZH视觉系统调试

淬火槽后自研机器人码垛、空冷后安川机器人拆垛、成品安川机器人码垛


CV_EXPORTS_W
void initUndistortRectifyMap(InputArray cameraMatrix, InputArray distCoeffs,
                             InputArray R, InputArray newCameraMatrix,
                             Size size, int m1type, OutputArray map1, OutputArray map2);
 计算不失真和校正变换映射。
/** @brief Computes the undistortion and rectification transformation map.

The function computes the joint undistortion and rectification transformation and represents the
result in the form of maps for remap. The undistorted image looks like original, as if it is
captured with a camera using the camera matrix =newCameraMatrix and zero distortion. In case of a
monocular camera, newCameraMatrix is usually equal to cameraMatrix, or it can be computed by
#getOptimalNewCameraMatrix for a better control over scaling. In case of a stereo camera,
newCameraMatrix is normally set to P1 or P2 computed by #stereoRectify .
该函数计算联合不失真和校正变换,并以映射的形式表示结果以进行重映射。未失真的图像看起来像原始图像,就好像它是使用camera matrix =newCameraMatrix 和零失真使用相机拍摄的一样。对于单目相机,newCameraMatrix 通常等于 cameraMatrix,或者可以通过#getOptimalNewCameraMatrix 计算以更好地控制缩放。对于立体相机,newCameraMatrix 通常设置为由 #stereoRectify 计算的 P1 或 P2。
Also, this new camera is oriented differently in the coordinate space, according to R. That, for
example, helps to align two heads of a stereo camera so that the epipolar lines on both images
become horizontal and have the same y- coordinate (in case of a horizontally aligned stereo camera).
此外,根据 R 的说法,这种新相机在坐标空间中的方向不同。例如,这有助于对齐立体相机的两个头部,以便两个图像上的核线变为水平并具有相同的 y 坐标(在水平对齐的立体相机的情况)。

该函数实际上为 remap 使用的逆映射算法构建映射。也就是说,对于目标(校正和校正)图像中的每个像素 \f$(u, v)\f$,该函数计算源图像(即来自相机的原始图像)中的相应坐标。应用以下过程:
The function actually builds the maps for the inverse mapping algorithm that is used by remap. That
is, for each pixel \f$(u, v)\f$ in the destination (corrected and rectified) image, the function
computes the corresponding coordinates in the source image (that is, in the original image from
camera). The following process is applied:
\f[
\begin{array}{l}
x  \leftarrow (u - {c'}_x)/{f'}_x  \\
y  \leftarrow (v - {c'}_y)/{f'}_y  \\
{[X\,Y\,W]} ^T  \leftarrow R^{-1}*[x \, y \, 1]^T  \\
x'  \leftarrow X/W  \\
y'  \leftarrow Y/W  \\
r^2  \leftarrow x'^2 + y'^2 \\
x''  \leftarrow x' \frac{1 + k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6}
+ 2p_1 x' y' + p_2(r^2 + 2 x'^2)  + s_1 r^2 + s_2 r^4\\
y''  \leftarrow y' \frac{1 + k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6}
+ p_1 (r^2 + 2 y'^2) + 2 p_2 x' y' + s_3 r^2 + s_4 r^4 \\
s\vecthree{x'''}{y'''}{1} =
\vecthreethree{R_{33}(\tau_x, \tau_y)}{0}{-R_{13}((\tau_x, \tau_y)}
{0}{R_{33}(\tau_x, \tau_y)}{-R_{23}(\tau_x, \tau_y)}
{0}{0}{1} R(\tau_x, \tau_y) \vecthree{x''}{y''}{1}\\
map_x(u,v)  \leftarrow x''' f_x + c_x  \\
map_y(u,v)  \leftarrow y''' f_y + c_y
\end{array}
\f]
where \f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6[, s_1, s_2, s_3, s_4[, \tau_x, \tau_y]]]])\f$
are the distortion coefficients.

在立体相机的情况下,此函数被调用两次:每个相机头一次,在 stereoRectify 之后,它又在 #stereoCalibrate 之后调用。 但是,如果立体相机没有校准,仍然可以使用#stereoRectifyUncalibrated 直接从基本矩阵计算校正变换。 对于每个相机,该函数将单应性 H 计算为像素域中的校正变换,而不是 3D 空间中的旋转矩阵 R。 R 可以从 H 计算为 \f[\texttt{R} = \texttt{cameraMatrix} ^{-1} \cdot \texttt{H} \cdot \texttt{cameraMatrix}\f] 其中可以任意选择cameraMatrix。
In case of a stereo camera, this function is called twice: once for each camera head, after
stereoRectify, which in its turn is called after #stereoCalibrate. But if the stereo camera
was not calibrated, it is still possible to compute the rectification transformations directly from
the fundamental matrix using #stereoRectifyUncalibrated. For each camera, the function computes
homography H as the rectification transformation in a pixel domain, not a rotation matrix R in 3D
space. R can be computed from H as
\f[\texttt{R} = \texttt{cameraMatrix} ^{-1} \cdot \texttt{H} \cdot \texttt{cameraMatrix}\f]
where cameraMatrix can be chosen arbitrarily.

@param cameraMatrix Input camera matrix \f$A=\vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ .
@param distCoeffs Input vector of distortion coefficients
\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6[, s_1, s_2, s_3, s_4[, \tau_x, \tau_y]]]])\f$
of 4, 5, 8, 12 or 14 elements. If the vector is NULL/empty, the zero distortion coefficients are assumed.
@param R Optional rectification transformation in the object space (3x3 matrix). R1 or R2 ,
computed by #stereoRectify can be passed here. If the matrix is empty, the identity transformation
is assumed. In cvInitUndistortMap R assumed to be an identity matrix.
@param newCameraMatrix New camera matrix \f$A'=\vecthreethree{f_x'}{0}{c_x'}{0}{f_y'}{c_y'}{0}{0}{1}\f$.
@param size Undistorted image size.
@param m1type Type of the first output map that can be CV_32FC1, CV_32FC2 or CV_16SC2, see #convertMaps
@param map1 The first output map.
@param map2 The second output map.
 */
@param cameraMatrix 输入相机矩阵 \f$A=\vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ 。
@param distCoeffs 失真系数的输入向量
\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6[, s_1, s_2, s_3, s_4[, \tau_x, \tau_y]]]])\f$
4、5、8、12 或 14 个元素。如果向量为 NULL/空,则假定零失真系数。
@param R 对象空间(3x3 矩阵)中的可选校正变换。 R1 或 R2 ,
由#stereoRectify 计算的可以在这里传递。如果矩阵为空,恒等变换
假设。在 cvInitUndistortMap R 假定为单位矩阵。
@param newCameraMatrix 新相机矩阵 \f$A'=\vecthreethree{f_x'}{0}{c_x'}{0}{f_y'}{c_y'}{0}{0}{1}\f$。
@param size 未失真的图像大小。
@param m1type 第一个输出映射的类型,可以是 CV_32FC1、CV_32FC2 或 CV_16SC2,参见 #convertMaps
@param map1 第一个输出映射。  undistortion 不失真映射1
@param map2 第二个输出映射。  undistortion 不失真映射2
 */



CV_EXPORTS_W void remap( InputArray src, OutputArray dst,
                         InputArray map1, InputArray map2,
                         int interpolation, int borderMode = BORDER_CONSTANT,
                         const Scalar& borderValue = Scalar());

对图像应用通用几何变换。
函数 remap 使用指定的映射转换源图像:
\f[\texttt{dst} (x,y) =  \texttt{src} (map_x(x,y),map_y(x,y))\f]

其中具有非整数坐标的像素值是使用一种可用的插值方法计算的。 \f$map_x\f$ 和 \f$map_y\f$ 可以编码为单独的浮点映射
分别在 \f$map_1\f$ 和 \f$map_2\f$ 中,或在 \f$map_1\f$ 中的 \f$(x,y)\f$ 的交错浮点映射,或定点映射 使用 convertMaps 创建的。 您可能希望将映射的浮点表示转换为定点表示的原因是它们可以产生更快(\~2x)的重新映射操作。 在转换后的情况下,\f$map_1\f$ 包含对 (cvFloor(x), cvFloor(y)) 并且 \f$map_2\f$ 包含插值系数表中的索引。

此功能无法就地运行。
@param src Source image.
@param dst Destination image. It has the same size as map1 and the same type as src .
@param map1 The first map of either (x,y) points or just x values having the type CV_16SC2 ,
CV_32FC1, or CV_32FC2. See convertMaps for details on converting a floating point
representation to fixed-point for speed.
@param map2 The second map of y values having the type CV_16UC1, CV_32FC1, or none (empty map
if map1 is (x,y) points), respectively.
@param interpolation Interpolation method (see #InterpolationFlags). The method #INTER_AREA is
not supported by this function.
@param borderMode Pixel extrapolation method (see #BorderTypes). When
borderMode=#BORDER_TRANSPARENT, it means that the pixels in the destination image that
corresponds to the "outliers" in the source image are not modified by the function.
@param borderValue Value used in case of a constant border. By default, it is 0.
@note
Due to current implementation limitations the size of an input and output images should be less than 32767x32767.
 */
@param src 源图像。
@param dst 目标图像。它的大小与 map1 相同,类型与 src 相同。
@param map1 第一个 (x,y) 点的映射,或者只是 x 类型为 CV_16SC2 的值,
CV_32FC1 或 CV_32FC2。有关转换浮点的详细信息,请参阅 convertMaps
表示为速度的定点。
@param map2 类型为 CV_16UC1、CV_32FC1 或无 y 值的第二个映射(空映射
如果map1是(x,y)点),分别。
@param interpolation 插值方法(请参阅#InterpolationFlags)。 #INTER_AREA 方法是
此功能不支持。
@param borderMode 像素外推法(参见#BorderTypes)。什么时候
borderMode=#BORDER_TRANSPARENT,表示目标图像中的像素
对应于源图像中的“异常值”未被函数修改。
@param borderValue 用于恒定边框的值。默认为 0。
@笔记
由于当前的实施限制,输入和输出图像的大小应小于 32767x32767。
 */


3. 

Mat estimateRigidTransform(InputArraysrc,InputArraydst,boolfullAffine)
前两个参数,可以是 :src=srcImage (变换之前的图片Mat)  dst=transImage(变换之后的图片Mat)
        也可以: src=array(变换之前的关键点Array) dst=array(变换之后的关键点Array)
第三个参数:  1(全仿射变换,包括:rotation, translation, scaling,shearing,reflection)

          0(带有约束的仿射变换) 

          默认参数1:全仿射变换。

fullAffine 与 partialAaffine 主要区别是:变换矩阵中后者可以是刚体变换。(不是必须,体会可以的含义)
也就可以后者没有尺度缩放。
 
fullAffine 的rotate矩阵可以是:
旋转矩阵可以没有任何数值上的约束。aii之间无数值上的约束。
paritcalAffine 的变换矩阵必须是如下类型:
旋转矩阵对角线元素的 绝对值 肯定相等。
https://blog.csdn.net/dongfang1984/article/details/52959308

///
/** @brief 解决一个或多个线性系统或最小二乘问题。

函数 cv::solve 解决线性系统或最小二乘问题(后者可以使用 SVD 或 QR 方法,或通过指定标志 #DECOMP_NORMAL ):
\f[\texttt{dst} = \arg \min _X \| \texttt{src1} \cdot \texttt{X} - \texttt{src2} \|\f]

如果使用#DECOMP_LU 或#DECOMP_CHOLESKY 方法,函数返回1
如果 src1 (或 \f$\texttt{src1}^T\texttt{src1}\f$ )是非奇异的。否则,它返回 0。在后一种情况下,dst 无效。在奇异的左侧部分的情况下,其他方法会找到伪解。

@note 如果你想找到一个未定义的统一范数解决方案
奇异系统 \f$\texttt{src1}\cdot\texttt{dst}=0\f$ ,函数solve 将不起作用。请改用 SVD::solveZ。

@param src1 系统左侧的输入矩阵。
@param src2 系统右侧的输入矩阵。
@param dst 输出解决方案。
@param flags 解决方案(矩阵反转)方法(#DecompTypes)
@sa 反转,SVD,特征
*/
CV_EXPORTS_W bool solve(InputArray src1, InputArray src2,
                        OutputArray dst, int flags = DECOMP_LU);
/** @brief Solves one or more linear systems or least-squares problems.

The function cv::solve solves a linear system or least-squares problem (the
latter is possible with SVD or QR methods, or by specifying the flag
#DECOMP_NORMAL ):
\f[\texttt{dst} =  \arg \min _X \| \texttt{src1} \cdot \texttt{X} -  \texttt{src2} \|\f]

If #DECOMP_LU or #DECOMP_CHOLESKY method is used, the function returns 1
if src1 (or \f$\texttt{src1}^T\texttt{src1}\f$ ) is non-singular. Otherwise,
it returns 0. In the latter case, dst is not valid. Other methods find a
pseudo-solution in case of a singular left-hand side part.

@note If you want to find a unity-norm solution of an under-defined
singular system \f$\texttt{src1}\cdot\texttt{dst}=0\f$ , the function solve
will not do the work. Use SVD::solveZ instead.

@param src1 input matrix on the left-hand side of the system.
@param src2 input matrix on the right-hand side of the system.
@param dst output solution.
@param flags solution (matrix inversion) method (#DecompTypes)
@sa invert, SVD, eigen
*/


/
CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d,
                                   double sigmaColor, double sigmaSpace,
                                   int borderType = BORDER_DEFAULT );
bilateralFilter
双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。

双边滤波器的好处是可以做边缘保存(edge preserving),一般用高斯滤波去降噪,会较明显地模糊边缘,对于高频细节的保护效果并不明显。双边滤波器顾名思义比高斯滤波多了一个高斯方差sigma-d,它是基于空间分布的高斯滤波函数,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。

/** @brief 将双边过滤器应用于图像。

该函数对输入图像应用双边过滤,如 http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html 中所述,双边过滤器可以很好地减少不需要的噪声,同时保持边缘相当清晰。但是,与大多数过滤器相比,它非常慢。

_Sigma 值_:为简单起见,您可以将 2 个 sigma 值设置为相同。如果它们很小(\<10),则滤镜不会有太大的效果,而如果它们很大(\> 150),它们会产生非常强烈的效果,使图像看起来“卡通”​​。

_Filter size_:大滤波器(d \> 5)非常慢,所以建议实时应用使用d=5,对于需要大噪声过滤的离线应用,可能使用d=9。

此过滤器不能就地工作。
@param src 源 8 位或浮点、1 通道或 3 通道图像。
@param dst 与 src 大小和类型相同的目标图像。
@param d 过滤期间使用的每个像素邻域的直径。如果是非正数,则从 sigmaSpace 计算。
@param sigmaColor 在颜色空间中过滤 sigma。较大的参数值意味着像素邻域内更远的颜色(参见 sigmaSpace)将混合在一起,导致
在较大的半等色区域。
@param sigmaSpace 在坐标空间中过滤 sigma。较大的参数值意味着更远的像素会相互影响,只要它们的颜色足够接近(参见 sigmaColor)。当 d\>0 时,它指定邻域大小,而不考虑 sigmaSpace。否则,d 与 sigmaSpace 成正比。
@param borderType 用于外推图像外像素的边框模式,请参阅#BorderTypes
 */
https://zhuanlan.zhihu.com/p/127023952 

双边滤波API
void bilateralFilter( InputArray src, 
                      OutputArray dst, 
                      int d,
                      double sigmaColor, 
                      double sigmaSpace,
                      int borderType = BORDER_DEFAULT );
参数:

第一个参数,InputArray类型的src,输入图像,即源图像,需要为8位或者浮点型单通道、三通道的图像。
第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
第三个参数,int类型的d,表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。
第四个参数,double类型的sigmaColor,颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
第五个参数,double类型的sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。
第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。


///
Canny()函数可以使用canny算法对输入图像进行边缘检测
https://blog.csdn.net/duwangthefirst/article/details/79971212 
CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,
                         double threshold1, double threshold2,
                         int apertureSize = 3, bool L2gradient = false );


/** @brief 使用 Canny 算法 @cite Canny86 查找图像中的边缘。

该函数在输入图像中查找边缘,并使用 Canny 算法在输出地图边缘中标记它们。 threshold1 和 threshold2 之间的最小值用于边缘链接。 最大值用于查找强边缘的初始段。 看
<http://en.wikipedia.org/wiki/Canny_edge_detector>

@param image 8 位输入图像。
@param edges 输出边缘图; 单通道 8 位图像,其大小与 image 相同。
@param threshold1 滞后过程的第一个阈值。
@param threshold2 滞后过程的第二个阈值。
@param 孔径大小 Sobel 算子的孔径大小。
@param L2gradient 一个标志,表示是否应该使用更准确的 \f$L_2\f$ norm \f$=\sqrt{(dI/dx)^2 + (dI/dy)^2}\f$ 来计算 图像梯度幅度 ( L2gradient=true ),或者默认 \f$L_1\f$ norm \f$=|dI/dx|+|dI/dy|\f$ 是否足够 ( L2gradient=false )。
  */

/** @brief Finds edges in an image using the Canny algorithm @cite Canny86 .

The function finds edges in the input image and marks them in the output map edges using the Canny algorithm. The smallest value between threshold1 and threshold2 is used for edge linking. The largest value is used to find initial segments of strong edges. See
<http://en.wikipedia.org/wiki/Canny_edge_detector>

@param image 8-bit input image.
@param edges output edge map; single channels 8-bit image, which has the same size as image .
@param threshold1 first threshold for the hysteresis procedure.
@param threshold2 second threshold for the hysteresis procedure.
@param apertureSize aperture size for the Sobel operator.
@param L2gradient a flag, indicating whether a more accurate \f$L_2\f$ norm \f$=\sqrt{(dI/dx)^2 + (dI/dy)^2}\f$ should be used to calculate the image gradient magnitude ( L2gradient=true ), or whether the default \f$L_1\f$ norm \f$=|dI/dx|+|dI/dy|\f$ is enough ( L2gradient=false ).
 */
cv::Canny(filterImg, cannyImg, 10, 250, 5);


//
/** @brief Finds circles in a grayscale image using the Hough transform.

The function finds circles in a grayscale image using a modification of the Hough transform.

Example: :
@include snippets/imgproc_HoughLinesCircles.cpp

@note Usually the function detects the centers of circles well. However, it may fail to find correct radii. You can assist to the function by specifying the radius range ( minRadius and maxRadius ) if you know it. Or, in the case of #HOUGH_GRADIENT method you may set maxRadius to a negative number to return centers only without radius search, and find the correct radius using an additional procedure.

It also helps to smooth image a bit unless it's already soft. For example, GaussianBlur() with 7x7 kernel and 1.5x1.5 sigma or similar blurring may help.

@param image 8-bit, single-channel, grayscale input image.
@param circles Output vector of found circles. Each vector is encoded as  3 or 4 element floating-point vector \f$(x, y, radius)\f$ or \f$(x, y, radius, votes)\f$ .
@param method Detection method, see #HoughModes. The available methods are #HOUGH_GRADIENT and #HOUGH_GRADIENT_ALT.
@param dp Inverse ratio of the accumulator resolution to the image resolution. For example, if dp=1 , the accumulator has the same resolution as the input image. If dp=2 , the accumulator has half as big width and height. For #HOUGH_GRADIENT_ALT the recommended value is dp=1.5,unless some small very circles need to be detected.
@param minDist Minimum distance between the centers of the detected circles. If the parameter is too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is
too large, some circles may be missed.
@param param1 First method-specific parameter. In case of #HOUGH_GRADIENT and #HOUGH_GRADIENT_ALT, it is the higher threshold of the two passed to the Canny edge detector (the lower one is twice smaller).
Note that #HOUGH_GRADIENT_ALT uses #Scharr algorithm to compute image derivatives, so the threshold value shough normally be higher, such as 300 or normally exposed and contrasty images.
@param param2 Second method-specific parameter. In case of #HOUGH_GRADIENT, it is the accumulator threshold for the circle centers at the detection stage. The smaller it is, the more false circles may be detected. Circles, corresponding to the larger accumulator values, will be returned first. In the case of #HOUGH_GRADIENT_ALT algorithm, this is the circle "perfectness" measure.The closer it to 1, the better shaped circles algorithm selects. In most cases 0.9 should be fine.If you want get better detection of small circles, you may decrease it to 0.85, 0.8 or even less.But then also try to limit the search range [minRadius, maxRadius] to avoid many false circles.
@param minRadius Minimum circle radius.
@param maxRadius Maximum circle radius. If <= 0, uses the maximum image dimension. If < 0, #HOUGH_GRADIENT returns
centers without finding the radius. #HOUGH_GRADIENT_ALT always computes circle radiuses.
@sa fitEllipse, minEnclosingCircle
 */
CV_EXPORTS_W void HoughCircles( InputArray image, OutputArray circles,
                               int method, double dp, double minDist,
                               double param1 = 100, double param2 = 100,
                               int minRadius = 0, int maxRadius = 0 );

/** @brief 使用霍夫变换在灰度图像中查找圆。

该函数使用 Hough 变换的修改在灰度图像中查找圆。

例子: :
@include 片段/imgproc_HoughLinesCircles.cpp

@note 通常该函数可以很好地检测圆心。但是,它可能无法找到正确的半径。如果您知道,您可以通过指定半径范围( minRadius 和 maxRadius )来协助该功能。或者,在 #HOUGH_GRADIENT 方法的情况下,您可以将 maxRadius 设置为负数以仅在不进行半径搜索的情况下返回中心,并使用附加过程找到正确的半径。

它还有助于使图像稍微平滑一些,除非它已经很柔和。例如,具有 7x7 内核和 1.5x1.5 sigma 或类似模糊的 GaussianBlur() 可能会有所帮助。

@param image 8 位、单通道、灰度输入图像。
@param circles 找到的圆的输出向量。每个向量被编码为 3 或 4 元素浮点向量 \f$(x, y, radius)\f$ 或 \f$(x, y, radius, votes)\f$ 。
@param method 检测方法,见#HoughModes。可用的方法是#HOUGH_GRADIENT 和#HOUGH_GRADIENT_ALT。
@param dp 累加器分辨率与图像分辨率的反比。例如,如果 dp=1 ,则累加器具有与输入图像相同的分辨率。如果 dp=2 ,累加器的宽度和高度只有一半。对于#HOUGH_GRADIENT_ALT,推荐值为dp=1.5,除非需要检测一些非常小的圆圈。
@param minDist 检测到的圆的中心之间的最小距离。如果参数太小,除了一个真实的圆圈外,可能还会错误地检测到多个相邻圆圈。如果是
太大,可能会漏掉一些圈子。
@param param1 第一个特定于方法的参数。在#HOUGH_GRADIENT 和#HOUGH_GRADIENT_ALT 的情况下,它是传递给 Canny 边缘检测器的两者中较高的阈值(较低的阈值小两倍)。
请注意,#HOUGH_GRADIENT_ALT 使用#Scharr 算法来计算图像导数,因此阈值通常会更高,例如 300 或正常曝光和对比度图像。
@param param2 第二个特定于方法的参数。在#HOUGH_GRADIENT 的情况下,它是检测阶段圆心的累加器阈值。它越小,可能检测到的错误圆圈就越多。与较大的累加器值相对应的圆圈将首先返回。在#HOUGH_GRADIENT_ALT 算法的情况下,这是圆形“完美度”度量。它越接近 1,表示圆形算法选择的形状越好。大多数情况下0.9就可以了。如果你想更好地检测小圆圈,你可以将它降低到0.85、0.8甚至更小。但也可以尝试限制搜索范围[minRadius,maxRadius]以避免出现很多错误的圆圈。
@param minRadius 最小圆半径。
@param maxRadius 最大圆半径。如果 <= 0,则使用最大图像尺寸。如果 < 0,#HOUGH_GRADIENT 返回
没有找到半径的中心。 #HOUGH_GRADIENT_ALT 总是计算圆半径。
@sa fitEllipse, minEnclosureCircle
 */
cv::HoughCircles(filterImg, circles, cv::HOUGH_GRADIENT, 1, 600, 120, 60, 150, 250);
cv::HoughCircles(cannyImg, circles, cv::HOUGH_GRADIENT, 1.5, 600, 130, 38, 150, 250);//霍夫圆检测

/
 
函数cvRound()、cvFloor()、cvCeil()都是按照一种舍入方式将浮点型数据转换为整型数据。

cvRound():返回跟参数最接近的整数值,即四舍五入;
cvFloor()  :返回不大于参数的最大整数值,即向下取整;
cvCeil()    :返回不小于参数的最小整数值,即向上取整;

/
CV_EXPORTS_W void circle(InputOutputArray img, Point center, int radius,
                       const Scalar& color, int thickness = 1,
                       int lineType = LINE_8, int shift = 0);
cv.circle(img,(520,430),300,(255,0,0),8)  # 在img原始图片中划圈,其圈的中心点为(520,430),半径=300,颜色为(255,0,0),粗细=8
cv.imshow('img1',img)
cv.imwrite('f.png',img)   # 存储有圈的图片

        //绘制圆心  
        circle(oriImg, circle_center_point, 3, cv::Scalar(255, 255, 0), -1, 8, 0);//在源图像上绘制圆心,实心圆
        //绘制圆轮廓  
        circle(oriImg, circle_center_point, radius, cv::Scalar(0, 50, 255), 3, 8, 0);
/** @brief 画一个圆圈。

函数 cv::circle 用给定的中心和半径绘制一个简单的或实心圆。
@param img 绘制圆圈的图像。
@param center 圆的中心。
@param radius 圆的半径。
@param color 圆圈颜色。
@param thickness 圆形轮廓的厚度,如果为正值。 负值,如#FILLED,表示要绘制一个实心圆。
@param lineType 圆边界的类型。 请参阅#LineTypes
@param shift 中心坐标和半径值中的小数位数。
  */ 
// 
CV_EXPORTS_W void rectangle(InputOutputArray img, Point pt1, Point pt2,
                          const Scalar& color, int thickness = 1,
                          int lineType = LINE_8, int shift = 0);                 
CV_EXPORTS_W void rectangle(InputOutputArray img, Rect rec,
                          const Scalar& color, int thickness = 1,
                          int lineType = LINE_8, int shift = 0);
/** @brief Draws a simple, thick, or filled up-right rectangle.

The function cv::rectangle draws a rectangle outline or a filled rectangle whose two opposite corners
are pt1 and pt2.

@param img Image.
@param pt1 Vertex of the rectangle.
@param pt2 Vertex of the rectangle opposite to pt1 .
@param color Rectangle color or brightness (grayscale image).
@param thickness Thickness of lines that make up the rectangle. Negative values, like #FILLED,
mean that the function has to draw a filled rectangle.
@param lineType Type of the line. See #LineTypes
@param shift Number of fractional bits in the point coordinates.
 */
/** @brief 绘制一个简单的、粗的或填充的右上矩形。

函数 cv::rectangle 绘制一个矩形轮廓或两个对角为 pt1 和 pt2 的填充矩形。

@param img 图片。
@param pt1 矩形的顶点。
@param pt2 与 pt1 相对的矩形的顶点。
@param color 矩形颜色或亮度(灰度图像)。
@param thickness 构成矩形的线条的粗细。 负值,如#FILLED,意味着函数必须绘制一个填充的矩形。
@param lineType 线的类型。 请参阅#LineTypes
@param shift 点坐标中的小数位数。
*/

/
CV_EXPORTS_W void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar& color,
                     int thickness=1, int line_type=8, int shift=0, double tipLength=0.1);
/** @brief 绘制一个从第一个点指向第二个点的箭头段。

函数 cv::arrowedLine 在图像中的 pt1 和 pt2 点之间绘制一个箭头。 另请参阅#line。

@param img 图片。
@param pt1 箭头开始的点。
@param pt2 箭头指向的点。
@param color 线条颜色。
@param thickness 线粗细。
@param line_type line的类型。 请参阅#LineTypes
@param shift 点坐标中的小数位数。
@param tipLength 相对于箭头长度的箭头尖端长度
  */

///
CV_EXPORTS_W void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color,
                     int thickness = 1, int lineType = LINE_8, int shift = 0);
/** @brief 绘制连接两点的线段。

函数 line 绘制图像中 pt1 和 pt2 点之间的线段。 该线被图像边界剪裁。 对于具有整数坐标的非抗锯齿线,使用 8 连通或 4 连通 Bresenham 算法。 粗线以四舍五入结尾。 使用高斯滤波绘制抗锯齿线。

@param img 图片。
@param pt1 线段的第一个点。
@param pt2 线段的第二个点。
@param color 线条颜色。
@param thickness 线粗细。
@param lineType 线的类型。 请参阅#LineTypes。
@param shift 点坐标中的小数位数。
  */


/** OpenCV color channel order is BGR[A] */
#define CV_RGB(r, g, b)  cv::Scalar((b), (g), (r), 0)

https://zhuanlan.zhihu.com/p/92021418 
cv::ml:SVM

cv::HOGDescriptor

    /**@brief 使用默认参数创建 HOG 描述符和检测器。

     等于 HOGDescriptor(Size(64,128), Size(16,16), Size(8,8), Size(8,8), 9 )
     */
         CV_WRAP HOGDescriptor() : winSize(64,128), blockSize(16,16), blockStride(8,8),
        cellSize(8,8), nbins(9), derivAperture(1), winSigma(-1),
        histogramNormType(HOGDescriptor::L2Hys), L2HysThreshold(0.2), gammaCorrection(true),
        free_coef(-1.f), nlevels(HOGDescriptor::DEFAULT_NLEVELS), signedGradient(false)
    {}  
 
 
    /** @重载
     @param _winSize 将 winSize 设置为给定值。
     @param _blockSize 将 blockSize 设置为给定值。
     @param _blockStride 将 blockStride 设置为给定值。
     @param _cellSize 将 cellSize 设置为给定值。
     @param _nbins 将 nbins 设置为给定值。
     @param _derivAperture 将 derivAperture 设置为给定值。
     @param _winSigma 将 winSigma 设置为给定值。
     @param _histogramNormType 将 histogramNormType 设置为给定值。
     @param _L2HysThreshold 将 L2HysThreshold 设置为给定值。
     @param _gammaCorrection 将 gammaCorrection 设置为给定值。
     @param _nlevels 将 nlevels 设置为给定值。
     @param _signedGradient 将signedGradient 设置为给定值。
     */
     CV_WRAP HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride,
                  Size _cellSize, int _nbins, int _derivAperture=1, double _winSigma=-1,
                  HOGDescriptor::HistogramNormType _histogramNormType=HOGDescriptor::L2Hys,
                  double _L2HysThreshold=0.2, bool _gammaCorrection=false,
                  int _nlevels=HOGDescriptor::DEFAULT_NLEVELS, bool _signedGradient=false)
    : winSize(_winSize), blockSize(_blockSize), blockStride(_blockStride), cellSize(_cellSize),
    nbins(_nbins), derivAperture(_derivAperture), winSigma(_winSigma),
    histogramNormType(_histogramNormType), L2HysThreshold(_L2HysThreshold),
    gammaCorrection(_gammaCorrection), free_coef(-1.f), nlevels(_nlevels), signedGradient(_signedGradient)
    {}
    
    
    /** @重载
     @param filename 包含线性 SVM 分类器的 HOGDescriptor 属性和系数的文件名。
     */
     HOGDescriptor (const String &filename)
 
    /** @重载
     @param d 克隆以创建新的 HOGDescriptor。
     */
     HOGDescriptor (const HOGDescriptor &d)
_winSize
_blockSize 是窗口中可滑动的块的大小
_blockStride  滑块动增量
_cellSize block中细胞单元的大小
_nbins bins的数量
https://www.cnblogs.com/whiteBear/p/10027348.html
https://www.cnblogs.com/luofeiju/p/13366846.html 
HOGDescriptor() : winSize(64,128), blockSize(16,16), blockStride(8,8),

        cellSize(8,8), nbins(9), derivAperture(1), winSigma(-1),

        histogramNormType(HOGDescriptor::L2Hys), L2HysThreshold(0.2), gammaCorrection(true),

        nlevels(HOGDescriptor::DEFAULT_NLEVELS)

        以上代码构造 HOGDescriptor 对象,主要参数意义如下:

        winSize:行人区域尺寸,在该尺寸上生成特征向量;对于大于该尺寸的行人,使用缩小到 winSize 尺寸以实现多尺度;应该注意的是,当行人尺寸较小时,无法通过放大到 winSize 尺寸实现检测;

        cellSize:在 cellSize 区域上构造梯度方向直方图;

        nbins:一个 cellSize 区域上形成梯度直方图的 bins;

        blockSize: 梯度方向直方图归一化尺寸,对 2 * 2 cells 进行归一化;

        blockStride:特征向量扫描步长,每次扫描增加 36 个特征点;
  2)hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector()) 设置默认行人分类器参数;
     3)detectMultiScale()检测行人,主要参数如下:
          vector<Rect>& foundLocations:输出检测行人矩形区域;
          vector<double>& foundWeights:输出检测行人置信度;
          double hitThreshold:线性分类器  中  取值,提升正类可信度;
          double scale:计算其他检测尺度,当 scale 越趋近 1,形成更多检测尺度,检测越细致;
          double finalThreshold:丢弃置信度小于 finalThreshold 区域;
    opencv 提供 samples peopledetect 给出了行人检测的使用示例,我修改了参数 hitThreshold = .3 以提升正类可信度,检测结果如下:数



 CV_WRAP virtual double getDecisionFunction(int i, OutputArray alpha, OutputArray svidx) const = 0;
/** @brief 检索决策函数

     @param i 决策函数的索引。 如果解决的问题是回归、1-class 或 2-class 分类,那么只有一个决策函数,并且索引应该始终为 0。否则,在 N-class 分类的情况下,将有 \f$N (N-1)/2\f$ 决策函数。
     @param alpha 权重的可选输出向量,对应于不同的支持向量。 在线性 %SVM 的情况下,所有的 alpha 都将是 1。
     @param svidx 支持向量矩阵中支持向量索引的可选输出向量(可以通过 SVM::getSupportVectors 检索)。 在线性的情况下
         %SVM 每个决策函数都由一个“压缩compressed”支持向量组成。

     该方法返回决策函数的 rho 参数,一个从加权中减去的标量
     内核响应的总和。
      */
      

//
    /**@brief Sets coefficients for the linear SVM classifier.
    @param svmdetector coefficients for the linear SVM classifier.
    @brief 设置线性 SVM 分类器的系数。
     @param svmdetector 线性 SVM 分类器的系数。
    */
    CV_WRAP virtual void setSVMDetector(InputArray svmdetector);

/
    /** Creates empty model.
    Use StatModel::train to train the model. Since %SVM has several parameters, you may want to
    find the best parameters for your problem, it can be done with SVM::trainAuto. 
    创建空模型。
     使用 StatModel::train 训练模型。 由于 %SVM 有多个参数,您可能希望为您的问题找到最佳参数,可以使用 SVM::trainAuto 来完成。*/
    CV_WRAP static Ptr<SVM> create();


 SVM::KernelTypes


//获取支持向量
/** @brief 检索所有支持向量

     该方法将所有支持向量作为浮点矩阵返回,其中支持向量存储为矩阵行。
      */
  CV_WRAP virtual Mat getSupportVectors() const = 0;

   /** @brief Retrieves the decision function

    @param i the index of the decision function. If the problem solved is regression, 1-class or  2-class classification, then there will be just one decision function and the index should  always be 0. Otherwise, in the case of N-class classification, there will be \f$N(N-1)/2\f$       decision functions.
    @param alpha the optional output vector for weights, corresponding to different support vectors.   In the case of linear %SVM all the alpha's will be 1's.
    @param svidx the optional output vector of indices of support vectors within the matrix of  support vectors (which can be retrieved by SVM::getSupportVectors). In the case of linear   %SVM each decision function consists of a single "compressed" support vector.

    The method returns rho parameter of the decision function, a scalar subtracted from the weighted  sum of kernel responses.
     */
     /** @brief 检索决策函数

     @param i 决策函数的索引。 如果解决的问题是回归、1-class 或 2-class 分类,那么只有一个决策函数,并且索引应该始终为 0。否则,在 N-class 分类的情况下,将有 \f$N (N-1)/2\f$ 决策函数。
     @param alpha 权重的可选输出向量,对应于不同的支持向量。 在线性 %SVM 的情况下,所有的 alpha 都将是 1。
     @param svidx 支持向量矩阵中支持向量索引的可选输出向量(可以通过 SVM::getSupportVectors 检索)。 在线性 %SVM 的情况下,每个决策函数都由单个“压缩”支持向量组成。

     该方法返回决策函数的 rho 参数,一个从内核响应的加权和中减去的标量。
      */
    CV_WRAP virtual double getDecisionFunction(int i, OutputArray alpha, OutputArray svidx) const = 0;  //输出新的alpha  svidx
    float rho          = model->getDecisionFunction(0, alphamat, svindex);//检索决策函数 
    
    


    Myhog.detectMultiScale(src, found, 0, cv::Size(16, 16), cv::Size(16, 16), 1.05, 2);//对图片进行多尺度检测  
HOG detectMultiScale 参数分析
https://www.cnblogs.com/klitech/p/5747895.html 
前段时间学习了HOG描述子及其与SVM结合在行人检测方面的应用。
可以看到一共有8个参数。

1.img(必需)

这个不用多解释,显然是要输入的图像。图像可以是彩色也可以是灰度的。

2.foundLocations

存取检测到的目标位置

3.hitThreshold (可选)

opencv documents的解释是特征到SVM超平面的距离的阈值(Threshold for the distance between features and SVM classifying plane)

所以说这个参数可能是控制HOG特征与SVM最优超平面间的最大距离,当距离小于阈值时则判定为目标。

4.winStride(可选)

HoG检测窗口移动时的步长(水平及竖直)。

winStride和scale都是比较重要的参数,需要合理的设置。一个合适参数能够大大提升检测精确度,同时也不会使检测时间太长。

5.padding(可选)

在原图外围添加像素,作者在原文中提到,适当的pad可以提高检测的准确率(可能pad后能检测到边角的目标?)

常见的pad size 有(8, 8), (16, 16), (24, 24), (32, 32).

6.scale(可选)
如图是一个图像金字塔,也就是图像的多尺度表示。每层图像都被缩小尺寸并用gaussian平滑。

scale参数可以具体控制金字塔的层数,参数越小,层数越多,检测时间也长。 一下分别是1.01  1.5 1.03 时检测到的目标。 通常scale在1.01-1.5这个区间

7.finalThreshold(可选)

这个参数不太清楚,有人说是为了优化最后的bounding box

8.useMeanShiftGrouping(可选)

bool 类型,决定是否应用meanshift 来消除重叠。

default为false,通常也设为false,另行应用non-maxima supperssion效果更好。


    virtual void detectMultiScale(InputArray img, CV_OUT std::vector<Rect>& foundLocations,
                                  double hitThreshold = 0, Size winStride = Size(),
                                  Size padding = Size(), double scale = 1.05,
                                  double finalThreshold = 2.0, bool useMeanshiftGrouping = false) const;
/** @brief 检测输入图像中不同大小的对象。 检测到的对象作为矩形列表返回。
     @param img CV_8U 或 CV_8UC3 类型的矩阵,包含检测到对象的图像。
     @param foundLocations 矩形向量,其中每个矩形都包含检测到的对象。
     @param hitThreshold 特征和 SVM 分类平面之间距离的阈值。
     通常为 0,应在检测器系数中指定(作为最后一个自由系数)。
     但如果自由系数被省略(这是允许的),您可以在此处手动指定。
     @param winStride 窗口步幅。 它必须是块步长的倍数。
     @param padding 填充
     @param scale 检测窗口增加的系数。
     @param finalThreshold 最终阈值
     @param useMeanshiftGrouping 表示分组算法
     */
                                  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值