OpenCV中常用算子

一、图像运算

	Mat src, src1, src2, dst;
	
	// 图像运算 加 减 乘 除
	cv::add(src1, src2, dst);                         // 相加:src1+src2
	cv::scaleAdd(src1, 1.0, src2, dst);               // 相加:1.0*src1+src2
	cv::addWeighted(src1, 0.3, src2, 0.7, 0.0, dst);  // 相加:0.3*src1+0.7*src2
	cv::subtract(src1, src2, dst);            // 相减:src1-src2
	cv::subtract(cv::Scalar(255), src, dst);  // 相减:255-src
	cv::subtract(src, cv::Scalar(128), dst);  // 相减:src-128
	cv::multiply(src1, src2, dst, 1.0);  // 相乘:src1*src2*1.0
	cv::mulTransposed(src, dst, true);   // 相乘:true:src'*src  false:src*src'
	cv::divide(src1, src2, dst, 1.0);    // 相除:src1/src2
	cv::divide(255.0, src, dst);         // 相除:255.0/src

二、按位运算

	// 按位运算 与 或 非 异或
	cv::bitwise_and(src1, src2, dst);  // 按位与操作 1&1=1 1&0=0 0&1=0 0&0=0
	cv::bitwise_or(src1, src2, dst);   // 按位或操作 1|1=1 1|0=1 0|1=1 0|0=0
	cv::bitwise_not(src, dst);         // 按位非操作 ~1=0 ~0=1
	cv::bitwise_xor(src1, src2, dst);  // 按位异或操作 1xor1=0 1xor0=1 0xor1=1 0xor0=1
	cv::bitwise_and(src, cv::Scalar(255), dst);

三、函数运算

    // 绝对值 开方 指数 对数 幂次方
	dst = cv::abs(src);   // 元素绝对值
	cv::sqrt(src, dst);   // 元素开方 x^(0.5)
	cv::exp(src, dst);    // 元素指数 e^x
	cv::log(src, dst);    // 元素自然对数 In(x)
	cv::pow(src, 5, dst); // 元素p次幂 x^5

四、像素比较

    // 较大值 较小值
	cv::max(src1, src2, dst);           // 两图像较大值
	cv::max(src, cv::Scalar(0), dst);   // 取较大值
	cv::min(src1, src2, dst);           // 两图像较小值
	cv::min(src, cv::Scalar(255), dst); // 取较小值

	// 像素比较,匹配标记255,否则0,输入src为单通道
	// CMP_EQ:=  CMP_GT:>  CMP_GE:>=  CMP_LT:<  CMP_LE:<=  CMP_NE:!=
	cv::compare(src1, src2, dst, cv::CMP_EQ);
	cv::compare(src, cv::Scalar(9), dst, cv::CMP_EQ);
	cv::compare(cv::Scalar(9), src, dst, cv::CMP_EQ);

	cv::Point posOutlier;  // [0.0, 256.0)
	bool flagRange = cv::checkRange(src, true, &posOutlier, 0.0, 256.0); // 检查值是否在范围内

	// 输入为单通道/多通道, 输出为单通道二值图像; 区间为闭区间
	Mat maskInRange;
	cv::inRange(gray, cv::Scalar(0), cv::Scalar(255), maskInRange);        // 相当于阈值分割
	cv::inRange(color, cv::Scalar(0,0,0), cv::Scalar(9,9,9), maskInRange); // 多通道之间取交集

五、通道操作

	// 通道合并 通道分离
	vector<Mat> mats;
	Mat grays[3] = { gray, gray, gray };
	cv::merge(mats, dst);      // 合并
	cv::merge(grays, 3, dst);  // 合并
	cv::split(dst, mats);   // 分离
	cv::split(dst, grays);  // 分离

	int fromTo[] = { 0, 0 };
	cv::mixChannels(&src, 1, &src, 1, fromTo, 1); // 通道重组

六、矩阵相关

	// 矩阵相关
	double det = cv::determinant(src);  // 行列式
	cv::Scalar trace = cv::trace(src);  // 计算矩阵的迹
	double norm1 = cv::norm(src, cv::NORM_L2);        // 矩阵范数
	double norm2 = cv::norm(src1, src2, cv::NORM_L2); // 矩阵范数
	int cntNonZero = cv::countNonZero(src); // 非零元素个数
	
	cv::transpose(src, dst);              // 转置
	cv::completeSymm(src, false);         // 上三角复制到下三角,使之对称
	cv::invert(src, dst, cv::DECOMP_LU);  // 矩阵求逆或伪逆
	cv::normalize(src, dst, 0.0, 1.0, cv::NORM_MINMAX);  // 映射到指定范围内

	Mat mtx = Mat::ones(100, 100, CV_8UC1);
	cv::setIdentity(mtx, cv::Scalar(255));  // 对角线元素设置为指定值,其他为0

	// 输入为浮点型对称方阵 输出特征值为向量 特征向量为矩阵
	Mat eigenvalues, eigenvectors;
	cv::eigen(src, eigenvalues, eigenvectors);

	// 协方差矩阵和均值
	Mat dstCovar, dstMean;
	cv::calcCovarMatrix(src, dstCovar, dstMean, 0, 6);

七、极值坐标

	// 寻找图像中灰度值最大最小位置  输入为单通道
	double minV, maxV;
	int minIdx[2], maxIdx[2];
	cv::Point minLoc, maxLoc;
	cv::minMaxIdx(src, &minV, &maxV, minIdx, maxIdx); 
	cv::minMaxLoc(src, &minV, &maxV, &minLoc, &maxLoc);

八、矩阵变换

	/* 透视变换 */
	Mat m33 = Mat::zeros(3, 3, CV_32FC1);
	cv::perspectiveTransform(src, dst, m33);  // 投影变换 3*3/4*4变换矩阵

	/* 线性变换 */
	Mat m22 = Mat::zeros(2, 2, CV_32FC1);
	cv::transform(src, dst, m22);  // 任意线性变换 2*2/2*3变换矩阵

	/* 仿射变换 透视变换 */
	cv::warpAffine(src, dst, m23, src.size());  // m23 为2*3变换矩阵
	cv::warpPerspective(src, dst, m33, src.size());  // m33为3*3变换矩阵

    perspectiveTransform / transform:变换矩阵与通道向量的乘积作为结果通道向量。

    warpAffine / warpPerspective:矩阵坐标位置变换。

九、其他算子

	// 矩阵求解
	Mat lhs, rhs, dstSolve;  // n*n  n*1  n*1   lhs*dstSolve=rhs
	cv::solve(lhs, rhs, dstSolve, cv::DECOMP_LU);  // 求解线性系统

	Mat coeffs, dstRoots;  // coeffs 4*1
	cv::solveCubic(coeffs, dstRoots);  // 三次多项式实根

	cv::solvePoly(coeffs, dstRoots);  // 任意多项式的根

	cv::sort(src, dst, cv::SORT_EVERY_ROW + SORT_ASCENDING);  // 分别对每行或列排序

	cv::sortIdx(src, dst, cv::SORT_EVERY_ROW + SORT_ASCENDING);  // 排序索引

	cv::flip(src, dst, 0);  // 绕x轴或y轴旋转 >0:y-flip  0:x-flip  <0:both

	// 广义矩阵乘法
	cv::gemm(src1, src2, 1.0, src, 1.0, dst, cv::GEMM_1_T + cv::GEMM_3_T);  // dst=1.0*src1'*src2+1.0*src

	// 幅值、角度相关
	Mat dstMagnitude, dstAngle;
	cv::cartToPolar(src, src, dstMagnitude, dstAngle); // 直角坐标系转为极坐标系

	Mat dstx, dsty;
	cv::polarToCart(dstMagnitude, dstAngle, dstx, dsty); // 极坐标中计算笛卡尔坐标

	cv::magnitude(src, src, dstMagnitude);  // 计算直角坐标系转换成极坐标系的幅值

	Mat dstPhase;
	cv::phase(src, src, dstPhase, false);  // 对二维矢量场计算笛卡尔-极坐标转换的方位角

	Mat vecMat1, vecMat2, dstIcovar;
	cv::Mahalanobis(vecMat1, vecMat2, dstIcovar);  // 计算两个向量的马氏距离

十、参考资料

    机器视觉算法(第10期)----图像处理中64个常用的算子 - 灰信网(软件开发博客聚合)