1 dmCornerDetect()二维码的精提取
bool PosGuide::dmCornerDetect(Mat _threshImg, //原始图片的矩阵信息
vector<Point2f> _rectPoints, //矩阵顶点顺时针排序后的顶点坐标
int _sampleDist, //提取的最靠近图片中心点的矩阵宽度*0.17
vector<Point2f>& _dmPoints)
1.1 opencv中的boundingRect()
Rect boundingRect( InputArray points );
将输入的点坐标,通过最小外接矩形,将他们包围,从而形成矩形区域。
举个栗子:
void test_boundingRect()
{
Mat image = Mat::zeros(240, 320, CV_8UC3);
vector<Point2f> visualRect;
//随意创建4个点坐标,寻找他们的最小外接矩形
visualRect.push_back(Point2f(5,5));
visualRect.push_back(Point2f(60,5));
visualRect.push_back(Point2f(150,30));
visualRect.push_back(Point2f(5,105));
Rect test = boundingRect(visualRect); //计算出最小外接矩形的左上顶点(x,y)和width, height
rectangle(image, Point(test.x, test.y), Point(test.width+test.x, test.height+test.y), Scalar(0,255,0), 2); //画出出矩形
imshow("origin picture", image); //画出图来
waitKey(0);
}
int main()
{
test_boundingRect();
return 0;
}
执行结果:
1.2 Mat的构造
Mat secGray(image.size(),CV_8UC1,Scalar::all(0));
创建一个和image一样大小的,8位无符号1通道,颜色为黑色的secGray 矩阵。
rotRects[i].size.width *0.17
为什么要乘0.17,sampledist向内扫描的控制距离。
2 extrLinePoints()
void PosGuide::extrLinePoints(Mat _img, //含有二维码的图片区域
Point2i _lstart, //矩阵顶点坐标
Point2i _lend,
bool _accelerate,
vector<Point2i>& _linePoints)
_accelerate是什么?,是否加速算法,如果sampledist>8即,二维码的信息较多,可以加速处理数据。如果sampledist<8,则认为信息较少,不加速处理数据。8为实验值!!!
if(_sampleDist>8) _accelerate=true;
extrLinePoints()函数时为了提取最小外接矩形四条边上的像素点信息,通过这些像素点信息,拟合出实际的边长所在的直线方程(使用detDMlines()函数)。
为了获得二维码的顶点oxdy的值,通过crossPointofLines()求解出四条直线的交点,然后对应顺序获得oxdy的四个点坐标。
这里的误差有很多,值得优化,提升精度
- 求解oxdy的真个过程感觉都很粗糙,
3 ctLocation()
3.1 colorDetect()
void PosGuide::colorDetect(Mat _srcImg, int _colorMode, Mat& _binaryImg)
3.2 HSV颜色空间
Hue------色调
Saturation-------饱和度
Value---------明度
3.3 opencv中的isContinuous()
cv::Mat::isContinuous(); //用来获得Mat矩阵的存储区域是否是连续的,如果连续则返回True;否则返回False。
如果Mat在存储一副图片时,在内存中时连续的,则可以看成一个一维数组,则可以通过成员指针,加快访问Mat图像中的数据,一般剪裁后的Mat就不再连续了,但是可以通过clone()他们,使得剪裁的部分重新连续。
1.4 opencv中Mat数据在内存中的存储
对于 m ∗ n m*n m∗n像素的1通道图像,在内存中存放是 n 行 ∗ m 列 ∗ 1 通 道 n行*m列*1通道 n行∗m列∗1通道 ,即Mat中的数据为 n ∗ m n*m n∗m的二位数组;单通道的图像每个列的像素只用1Byte=8bit表示,范围为0~255( 2 8 − 1 2^8-1 28−1),白,黑,和之间渐变的色
对于 m ∗ n m*n m∗n像素的3通道图像,在内存中存放是 n 行 ∗ m 列 ∗ 3 通 道 n行*m列*3通道 n行∗m列∗3通道,即Mat中的数据为 n ∗ 3 m n*3m n∗3m 的二位数组;3通道的图像每个列的图像用3Byte表示,即R,G,B各占1Byte=8bit,范围都是0~255( 2 8 − 1 2^8-1 28−1)
对于 m ∗ n m*n m∗n像素的4通道图像,在内存中存放是 n 行 ∗ m 列 ∗ 4 通 道 n行*m列*4通道 n行∗m列∗4通道 ,即Mat中的数据为 n ∗ 3 m n*3m n∗3m 的二位数组;4通道的图像每个列的图像用4Byte表示,即R,G,B,Alpha各占1Byte=8bit,范围都是0~255( 2 8 − 1 2^8-1 28−1)。
举个栗子1:
//单通道9*5像素的图片,每一个元素都表示一种颜色
[0,0,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,0]
举个栗子2:
举个栗子3:
同样,如果是HSV颜色空间,则1个像素使用3Byte,其中H,S,V分别占用1bit,范围为H:0~180; S,V: 0~255。
2 HSV颜色分量范围(估计值,并不准确)
部分红色倍归类到了紫色里面
3 opencv中Mat::setTo()
就是将对应的矩阵设置成指定的值。
setTo()有两个输入参数,
Mat& setTo(InputArray value, InputArray mask=noArray());
- 如果mask矩阵所有元素为0,则setTo(value, mask)无效
- 如果mask矩阵元素不为0,则setTo(value, mask)有效,
- 如果没有mask矩阵,默认mask不为0,setTo(value)有效。
注意setTo()是引用
举个栗子1:
void test_Mat_setTo()
{
Mat origin1(3,3, CV_8UC1, Scalar::all(0));
Mat mask(origin.size(), CV_8UC1, Scalar::all(0));
origin.setTo(3);
cout << "mask = " << endl << mask << endl;
cout << "origin = " << endl << origin << endl;
}
执行结果1:
mask =
[0, 0, 0;
0, 0, 0;
0, 0, 0]
origin =
[3, 3, 3;
3, 3, 3;
3, 3, 3]
Press <RETURN> to close this window...
举个栗子2:
void test_Mat_setTo()
{
Mat origin1(3,3, CV_8UC1, Scalar::all(0));
Mat mask(origin.size(), CV_8UC1, Scalar::all(0));
origin.setTo(3,mask);
cout << "mask = " << endl << mask << endl;
cout << "origin = " << endl << origin << endl;
}
执行结果2:
mask =
[0, 0, 0;
0, 0, 0;
0, 0, 0]
origin =
[0, 0, 0;
0, 0, 0;
0, 0, 0]
Press <RETURN> to close this window...
举个栗子3:
void test_Mat_setTo()
{
Mat origin1(3,3, CV_8UC1, Scalar::all(0));
Mat mask(origin.size(), CV_8UC1, Scalar::all(1));
origin.setTo(3,mask);
cout << "mask = " << endl << mask << endl;
cout << "origin = " << endl << origin << endl;
}
执行结果3:
mask =
[1, 1, 1;
1, 1, 1;
1, 1, 1]
origin =
[3, 3, 3;
3, 3, 3;
3, 3, 3]
Press <RETURN> to close this window...