Opencv 基本图形处理以及数据处理方法

  1. Opencv例子参考
    1. 获取圆中心例子参考

//【1】Mat变量定义  

Mat midImage;//目标图的定义

//【2】转为灰度图并进行图像平滑

cvtColor(frame,midImage, CV_BGR2GRAY);//转化边缘检测后的图为灰度图

GaussianBlur( midImage, midImage, Size(9, 9), 2, 2 );

 

//【3】进行霍夫圆变换

vector<Vec3f> circles;

HoughCircles( midImage, circles, CV_HOUGH_GRADIENT,1.5, 10, 200, 100, 0, 0 );

//【4】依次在图中绘制出圆

for( size_t i = 0; i < circles.size(); i++ )

{

//参数定义

Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));

int radius = cvRound(circles[i][2]);

//绘制圆心

circle( frame, center, 3, Scalar(0,255,0), -1, 8, 0 );

//绘制圆轮廓

circle( frame, center, radius, Scalar(155,50,255), 3, 8, 0 );

//打印圆心坐标

printf("x = %d,y = %d\n",cvRound(circles[i][0]),cvRound(circles[i][1]));

}

//【5】显示效果图  

namedWindow("效果");

imshow("效果", frame2);

c = cvWaitKey(30);

if (c == 27)//Esc键退出

{

break;

}

return 0;  

}

/*----------------------------------------各参数的意思----------------------------------------

cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );

InputArray src: 输入图像即要进行颜色空间变换的原图像,可以是Mat类 

OutputArray dst: 输出图像即进行颜色空间变换后存储图像,也可以Mat类 

int code: 转换的代码或标识,即在此确定将什么制式的图片转换成什么制式的图片

int dstCn = 0: 目标图像通道数,如果取值为0,则由src和code决定

 

 

 

 

    1. 基本图像处理
      1. 二值化

cvThreshold(src, dst,120, 255, CV_THRESH_BINARY)

 

      1. 灰度化

cvtColor(frame,midImage, CV_BGR2GRAY);//转化边缘检测后的图为灰度图

cvCvtColor (img, img1, CV_RGB2GRAY); //转为单通道

      1. 滤波
        1. GaussianBlur 滤波

GaussianBlur( midImage, midImage, Size(9, 9), 2, 2 );

gaus = cv.GaussianBlur(img, (3, 3), 0)

C++: void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )

参数解释:

. InputArray src: 输入图像,可以是Mat类型,图像深度为CV_8U、CV_16U、CV_16S、CV_32F、CV_64F。

. OutputArray dst: 输出图像,与输入图像有相同的类型和尺寸。

. Size ksize: 高斯内核大小,这个尺寸与前面两个滤波kernel尺寸不同,ksize.width和ksize.height可以不相同但是这两个值必须为正奇数,如果这两个值为0,他们的值将由sigma计算。

. double sigmaX: 高斯核函数在X方向上的标准偏差

. double sigmaY: 高斯核函数在Y方向上的标准偏差,如果sigmaY是0,则函数会自动将sigmaY的值设置为与sigmaX相同的值,如果sigmaX和sigmaY都是0,这两个值将由ksize.width和ksize.height计算而来。具体可以参考getGaussianKernel()函数查看具体细节。建议将size、sigmaX和sigmaY都指定出来。

. int borderType=BORDER_DEFAULT: 推断图像外部像素的某种便捷模式,有默认值BORDER_DEFAULT,如果没有特殊需要不用更改,具体可以参考borderInterpolate()函数。

为了能更直观的观察到四个变量对滤波的影响,建立四个轨迹条分别调节,所以最后运行结果图片有点丑,示例代码如下:

        1. medianBlur

参数解释:

. InputArray src: 输入图像,图像为1、3、4通道的图像,当模板尺寸为3或5时,图像深度只能为CV_8U、CV_16U、CV_32F中的一个,如而对于较大孔径尺寸的图片,图像深度只能是CV_8U。

. OutputArray dst: 输出图像,尺寸和类型与输入图像一致,可以使用Mat::Clone以原图像为模板来初始化输出图像dst

. int ksize: 滤波模板的尺寸大小,必须是大于1的奇数,如3、5、7……

————————————————

版权声明:本文为CSDN博主「梧桐栖鸦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/keith_bb/article/details/54426920

      1. 边缘检测

http://blog.sina.com.cn/s/blog_13fa7509b0102xhmk.html

        1. Canny

laplace = cv2.Laplacian(gray, cv2.CV_8U, ksize=3)

sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 1)

def Canny(image,threshold1,threshold2,edges=None,apertureSize=None,L2gradient=None)

threshold1:int类型的,低阈值

threshold2:int类型的,高阈值

edeges:单通道存储边缘的输出图像

apertureSize:Sobel算子内核(kSize)大小

L2gradiend:Bool类型的,为真表示使用更精确的L2范数进行计算(两个方向的倒数的平方再开放),为假表示用L1范数(直接将两个方向导数的绝对值相加)

Mat edges;

Canny(edges, edges, 40, 120, 3);

        1. Sobel

OpenCV Sobel()函数

复制代码

 1 C++: void Sobel (

 2 InputArray src,//输入图

 3  OutputArray dst,//输出图

 4  int ddepth,//输出图像的深度

 5  int dx,

 6  int dy,

 7  int ksize=3,

 8  double scale=1,

 9  double delta=0,

10  int borderType=BORDER_DEFAULT );

复制代码

第一个参数,InputArray 类型的src,为输入图像,填Mat类型即可。

第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。

第三个参数,int类型的ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合:

                若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F

                若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F

                若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F

                若src.depth() = CV_64F, 取ddepth = -1/CV_64F

第四个参数,int类型dx,x 方向上的差分阶数。

第五个参数,int类型dy,y方向上的差分阶数。

第六个参数,int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。

第七个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。

我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。

第八个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。

第九个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。

这个参数可以在官方文档中borderInterpolate处得到更详细的信息。

一般情况下,都是用ksize x ksize内核来计算导数的。

然而,有一种特殊情况——当ksize为1时,往往会使用3 x 1或者1 x 3的内核。

且这种情况下,并没有进行高斯平滑操作。

      1. 膨胀,腐蚀

Mat hline = getStructuringElement(MORPH_RECT, Size(dstImage.cols / 33, 1), Point(-1, -1));

Mat vline = getStructuringElement(MORPH_RECT, Size(1, dstImage.rows / 19), Point(-1, -1));

Mat rect = getStructuringElement(MORPH_RECT, Size(1, 1), Point(-1, -1));

erode(dstImage, temp, rect);

  • erode(const Mat &src, Mat &dst, Mat kernel, Point anchor=Point(-1,-1), int iterations=1)
  • src:輸入圖,可以多通道,深度可為CV_8U、CV_16U、CV_16S、CV_32F或CV_64F。
  • dst:輸出圖,和輸入圖尺寸、型態相同。
  • kernel:結構元素,如果kernel=Mat()則為預設的3×3矩形,越大侵蝕效果越明顯。
  • anchor:原點位置,預設為結構元素的中央。
  • iterations:執行次數,預設為1次,執行越多次侵蝕效果越明顯。

 

dilate(temp, dst1, rect);

dilate(const Mat &src, Mat &dst, Mat kernel, Point anchor=Point(-1,-1), int iterations=1)

  • src:輸入圖,可以多通道,深度可為CV_8U、CV_16U、CV_16S、CV_32F或CV_64F。
  • dst:輸出圖,和輸入圖尺寸、型態相同。
  • kernel:結構元素,如果kernel=Mat()則為預設的3×3矩形,越大膨脹效果越明顯。
  • anchor:原點位置,預設為結構元素的中央。
  • iterations:執行次數,預設為1次,執行越多次膨脹效果越明顯。

 

      1. 开运算
      2. 闭运算
      3. 图案边缘和中心检测。
  1. 检测圆心,circles=CvHoughCircles(img,Storage,...);
    p=(float*)CvGetSeqElem(circles,i);

利用opencv进行图像处理,提取椭圆圆心处理

写这个是因为项目正好在做这个,所以简单写写提取椭圆圆心坐标的代码,用的软件是VS。

首先介绍一下步骤,直接从图像处理开始

1,二值化处理(threhold())

2,高斯滤波(GaussianBlur())

3,轮廓提取(canny算子)

4,寻找闭合轮廓(findContours())

https://blog.csdn.net/hust_bochu_xuchao/article/details/52230694

 

上面介绍的是提取椭圆轮廓过程,下面介绍的是过滤干扰图像的过程,分三步,不过,这三部也不都是必须的,看个人需求:

1,像素点数量过滤(size)

2,面积过滤

3,长宽比过滤

代码如下,比较简单,就不过多介绍了,欢迎留言:

原文链接:https://blog.csdn.net/weixin_44540503/article/details/88597691

二值化:cvThreshold(src, src,120, 255, CV_THRESH_BINARY);   // 二值化

cvThreshold

 

cvWaitKey(0);

cv::WaitKey(0);

 

      1. 圆查找

 

#include<cv.h>#include<highgui.h>int main(){ IplImage* src = NULL; IplImage* dst = NULL; IplImage* color = NULL; src = cvLoadImage ("circle.jpg", 1); dst = cvCreateImage (cvGetSize(src), IPL_DEPTH_8U, 1);

if (src->nChannels == 1) {  dst = cvCloneImage (src); }

else

cvCvtColor (src, dst, CV_RGB2GRAY);

}

CvMemStorage* storage = cvCreateMemStorage (0); cvSmooth (dst, dst, CV_GAUSSIAN, 5, 5);

 CvSeq* circles = cvHoughCircles (dst, storage, CV_HOUGH_GRADIENT, 2, dst->width / 3, 300, 100, 0, 200);

color = cvCreateImage (cvGetSize(src), IPL_DEPTH_8U, 3);

cvCvtColor (dst, color, CV_GRAY2RGB);

for (int i = 0; i < circles->total; i++) {  float* p = (float*)cvGetSeqElem (circles, i); 

CvPoint pt = cvPoint (cvRound(p[0]), cvRound(p[1])); 

cvCircle (color, pt, cvRound(p[2]), CV_RGB(255, 0, 0), 3, 8, 0); }

cvNamedWindow ("src", 1);

cvShowImage ("src", src);

cvNamedWindow ("circle", 1);

cvShowImage ("circle", color);

cvWaitKey (0);

cvReleaseMemStorage (&storage);

cvReleaseImage (&src);

cvReleaseImage (&dst);

cvReleaseImage (&color); return 0;}

 

 

 

霍夫圆变换的函数为:

HoughCircles

利用 Hough 变换在灰度图像中找圆

CvSeq* cvHoughCircles( CvArr* image, void* circle_storage, int method, double dp, double min_dist, double param1=100, double param2=100, int min_radius=0, int max_radius=0 );

image

输入 8-比特、单通道灰度图像.

circle_storage

检测到的圆存储仓. 可以是内存存储仓 (此种情况下,一个线段序列在存储仓中被创建,并且由函数返回)或者是包含圆参数的特殊类型的具有单行/单列的CV_32FC3型矩阵(CvMat*). 矩阵头为函数所修改,使得它的 cols/rows 将包含一组检测到的圆。如果 circle_storage 是矩阵,而实际圆的数目超过矩阵尺寸,那么最大可能数目的圆被返回

. 每个圆由三个浮点数表示:圆心坐标(x,y)和半径.

 

method

Hough 变换方式,目前只支持CV_HOUGH_GRADIENT, which is basically 21HT, described in [Yuen03].

累加器图像的分辨率。这个参数允许创建一个比输入图像分辨率低的累加器。(这样做是因为有理由认为图像中存在的圆会自然降低到与图像宽高相同数量的范畴)。如果dp设置为1,则分辨率是相同的;如果设置为更大的值(比如2),累加器的分辨率受此影响会变小(此情况下为一半)。dp的值不能比1小。

Resolution of the accumulator used to detect centers of the circles. For example, if it is 1, the accumulator will have the same resolution as the input image, if it is 2 - accumulator will have twice smaller width and height, etc.

min_dist

该参数是让算法能明显区分的两个不同圆之间的最小距离。

Minimum distance between 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.

param1

用于Canny的边缘阀值上限,下限被置为上限的一半。

The first method-specific parameter. In case of CV_HOUGH_GRADIENT it is the higher threshold of the two passed to Canny edge detector (the lower one will be twice smaller).

param2

累加器的阀值。

The second method-specific parameter. In case of CV_HOUGH_GRADIENT it is accumulator threshold at the center detection stage. The smaller it is, the more false circles may be detected. Circles, corresponding to the larger accumulator values, will be returned first.

min_radius

最小圆半径。

Minimal radius of the circles to search for.

max_radius

最大圆半径。

Maximal radius of the circles to search for. By default the maximal radius is set to max(image_width, image_height).

The function cvHoughCircles finds circles in grayscale image using some modification of Hough transform.

 

img1,

storage,

CV_HOUGH_GRADIENT,

1, //累加器图像的分辨率,增大则分辨率变小

18, //很重要的一个参数,告诉两个圆之间的距离的最小距离,如果已知一副图像,可以先行计

//算出符合自己需要的两个圆之间的最小距离。

100, //canny算法的阈值上限,下限为一半(即100以上为边缘点,50以下抛弃,中间视是否相连而//定)

25, //决定成圆的多寡 ,一个圆上的像素超过这个阈值,则成圆,否则丢弃

32,//最小圆半径,这个可以通过图片确定你需要的圆的区间范围

45 //最大圆半径

);

img2 = cvCreateImage (cvGetSize(img), IPL_DEPTH_8U, 3); //用一个三通道的图片来显示红色的

https://blog.csdn.net/weixin_41695564/article/details/80099917

https://blog.csdn.net/MnisRain/article/details/82048840?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.nonecase

https://blog.csdn.net/weixin_44540503/article/details/88597691

      1. 检测直线

https://blog.csdn.net/gdut2015go/article/details/46430699

  1. Opencv数据操作处理
    1. 数据类型

 

    1. Vec:向量
      1. vector<int> v; 定义变量

定义:Vec2b,Vec3b,Vec2s,Vec3s

//【1】向量模板类Vec的实例化,并且给相应实例的Vec向量模板类实例---指定新的名字

         //【1】Vec2b--这是一个具体的--类类型---这个类类型实例话的类对象表示如下所示:

         //【1】Vec2b---表示每个Vec2b对象中,可以存储2个char(字符型)数据

         typedef Vec<uchar, 2> Vec2b; 、

         //【2】Vec3b---表示每一个Vec3b对象中,可以存储3个char(字符型)数据,比如可以用这样的对象,去存储RGB图像中的一个像素点

         typedef Vec<uchar, 3> Vec3b;

         //【3】Vec4b---表示每一个Vec4b对象中,可以存储4个字符型数据,可以用这样的类对象去存储---4通道RGB+Alpha的图像中的像素点

         typedef Vec<uchar, 4> Vec4b;

            

         //【1】Vec2s---表示这个类的每一个类对象,可以存储2个short int(短整型)的数据

         typedef Vec<short, 2> Vec2s;

         typedef Vec<short, 3> Vec3s;

      1. vector 修改

    vector<Vec3f> pcircles;

                  Point center((pcircles[i][0]), (pcircles[i][1]));圆心  cvRound 返回和参数最接近的整数值                                                                                                     

                  int radius = (pcircles[i][2]);   //提取半径           

 

v.resize(3);    /*reserve表示容器预留空间,但并不是真正的创建对象,需要通过insert()或push_back()等创建对象,默认对象为0*/

for (int i = 0; i < v.size(); i++)

    v[i] = i;

v.resize(5)     /*resize容器v的大小为5,前三个初始化的值不变,0/1/2,后面的默认为0*/

v.size()        /*v的size为5*/

v.push_back(6)  /*在v的最后面添加一个6*/

v.size()    /* v的size为6,v的值分别是0/1/2/0/0/6 */

      1. vector 排序

 对于vector的全体排序,我们知道sort(vv.begin(),vv.end())来进行的。

 

    1. Scalar:标量

Scalar(0,0,255))

CvScalar color = CV_RGB(255,0,0);是什么意思,其中color是自己定义的吗?

是自己定义的,你可以随便写,但是一般都用color,为了便于认知。在Opencv中,cvScalar是CV_RGB的宏,cvScalar的储存顺序是B-G-R,而CV_RGB的储存顺序是R-G-B,两者正好相反,所以你的cvScalar(255,0,0),实际意思是B=255,当然是蓝色的

————————————————

版权声明:本文为CSDN博主「zqx951102」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/zqx951102/article/details/82797484

 

    1. Point:点定义和修改

操作         例子(3可以换成2

默认构造方法        cv::Point3i p;

拷贝构造方法        cv::Point3f p2( p1 );

带初始化值的构造方法        cv::Point3d p( x0, x1, x2 );

转换到固定向量类        (cv::Vec3f) p;

成员访问        p.x; p.y;p.z(2的时候没有z)

点积操作        float x = p1.dot( p2 )

双精度点积操作    double x = p1.ddot( p2 )

矢量积操作    p1.cross( p2 )(只针对3point

判断point是否在矩阵r p.inside( r )(只针对2point

————————————————

版权声明:本文为CSDN博主「yuanCruise」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qiu931110/article/details/85174246

Point(int x, int y) //建構式

Point pt1(20,30);

Point pt2;

pt2.x = 20;

pt2.y = 30;

 

    1. Rect:矩形

Rect:矩形類別,成員有x、y、width、height,分別表示左上角頂點的x座標,左上角頂點的y座標,矩形寬、矩形高,可用area()函式得到面積,以下為建構式和最基本的兩種賦值方法:

 

Rect(int x, int y, int width, int height) //建構式

Rect rect1(20,30,150,100);

Rect rect2;

rect2.x = 20;

rect2.y = 30;

rect2.width = 150;

rect2.height = 100;

int myRectArea = rect2.area();

 

    1. Size:大小

Size:尺寸類別,成員有width和height,分別表示寬和長(int型態),可用area()函式得到面積,以下為建構式最基本兩種賦值方法:

Size(int width, int height) //建構式

Size size1(150, 100);

Size size2;

size2.width = 150;

size2.height = 100;

int myArea = size2.area();

Size2f:尺寸類別,和Size用法雷同,只是width和height為float型態。

 

 

    1. RotatedRect

RotatedRect:斜矩形類別,成員有矩形的質心center(Point2f類別),四周長size(Size2f類別)、旋轉角度angle(float類別),可用points()函式得到四個頂點,以下為建構式和最基本的兩種賦值方法:

RotatedRect(const Point2f &center, const Size2f &size, float angle) //建構式

RotatedRect rRect1(Point2f(150,150), Size2f(100,50), 30.0);

RotatedRect rRect2;

rRect2.center = Point2f(150,150);

rRect2.size = Size2f(100,50);

rRect2.angle = 30.0;

Point2f vertices[4];

rRect2.points(vertices);

 

    1. Mat矩阵
      1. 矩阵定义
        1. 单通道图和3通道图

Mat rawImg(600, 500, CV_8U, Scalar(0)); //这个Scalar函数有啥作用呢?,我们我猜想是灰度值  0是全黑图。255是全白。

//Mat resultImg; 

namedWindow("Raw Image"); 

imshow("Raw Image", rawImg); 

waitKey(0); 

destroyAllWindows(); 

imwrite("图像.jpg",rawImg); 

Mat rawImg(600, 500, CV_8UC3, Scalar(255, 0, 0));   彩色3单通道图

        1. 零矩阵,单位矩阵

https://www.cnblogs.com/Jack-Lee/p/3652957.html

cv::Mat mz = cv::Mat::zeros(cv::Size(5,5),CV_8UC1); // 全零矩阵

         cv::Mat mo = cv::Mat::ones(cv::Size(5,5),CV_8UC1);  // 全1矩阵

         cv::Mat me = cv::Mat::eye(cv::Size(5,5),CV_32FC1);  // 对角线为1的对角矩阵

         cout<<"mz = "<<endl<<mz<<endl<<endl;

         cout<<"mo = "<<endl<<mo<<endl<<endl;

         cout<<"me = "<<endl<<me<<endl<<endl;

————————————————

版权声明:本文为CSDN博主「iracer」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/iracer/article/details/51296631

 

      1. 矩阵访问
  1. at方法,srcImage.at<uchar>(14,25) = 25
  2.      指针方法  uchar *pSrcData = srcImg.ptr<uchar>(i);
  3. uchar *data = Circle_Point_Matrix_c1_sort_id.ptr<uchar>(0);//获取第一行的首地址
  4. int a = data[0];//获取第五行第五列的像素值并幅值给a。
  5. cout << "a=" << a << endl;  //第2列
  6. s = cvGet2D(src, j,i);//获取src图像中坐标为(i,j)的像素点的值
  7.  

 

https://zhuanlan.zhihu.com/p/60607828

获取某点像素值的方法

在输出像素值,不要直接用cout输出,将获得的像素幅值给一个变量,用cout输出这个变量。

1、ptr方法

    mat类提供了ptr函数获取任意行的首地址,例如ptr[i]返回第i行的首地址。

    例子:获取坐标【5,5】的像素值

        Mat TrainData=imread("C:\\Users\\andy\\Desktop\\特征图片.jpg",1);

        uchar *data=TrainData.ptr<uchar>(5);//获取第五行的首地址

        int a =data[5];//获取第五行第五列的像素值并幅值给a。

        cout<<a<<endl;//输出像素值

2、at 操作取矩阵值

    试了好多次数,终于摸到一下at的用法,例子如下。   

    Mat=trainData=imread("D:/Opencv_tutorials_Learning/ML_Svm/SvmLearn/1.jpg",1);      

int b=trainData.at<Vec3b>(1,10)[0];//这句话可以输出坐标(1,10)位置的0通道像素值,也就是B通道值

cout<<trainData.at<Vec3b>(1,10)[0]<<endl;//此语句可以运行,但运行时候没有输出任何值,但输出了换行

cout<<trainData.at<Vec3b>(1,10)<<endl;//此语句可以输出三通道的值,例如[230 222 102].

3、迭代器,这个方法比较复杂,初学就不考虑了。

————————————————

版权声明:本文为CSDN博主「mikedadong」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/mikedadong/article/details/51133139

 

1、若是灰度图,就是单通道图像,获取的就是每一个像素点的灰度值。

 

IplImage* img = cvLoadImage("test.bmp", 0);

    for (int i = 0; i < img->height; i++)

    {

        for (int j = 0; j < img->width; j++)

        {

            //方法一:使用cvGet2D()函数间接访问

            CvScalar s = cvGet2D(img, i, j);//注:i代表y轴,即height;j代表x轴,即width。

            printf("gray value=%f\n",s.val[0]);

 

            //方法二:使用直接访问

            uchar val = ((uchar *)(img->imageData + i*img->widthStep))[j];  //i和j的意义同上

            printf("gray value=%d\n",val);

        }

    }

      1. OpenCV Mat数据的按行(列)和多行(列)赋值

https://blog.csdn.net/u014686356/article/details/65937750

赋值的不正确情况

在使用opencv的过程中,希望多行或者多列进行赋值,我之前的代码是这样的

    Mat c = Mat::zeros(3, 5, CV_32F);

    Mat a = Mat::ones(3, 6, CV_32F);

    //对a的第一列进行赋值

    a.col(0) = c.col(0);

    //将c的1-5列赋值给a

    a.colRange(1, 6) = c;

可以试一下。这时的a的值没有发生任何变化

使用copyTo函数

使用copyTo函数可以实现数据的复制,是一种克隆,而且可以实现单行(列),多行(列)的赋值;

代码如下

 

    Mat c = Mat::zeros(3, 5, CV_32F);

    Mat a = Mat::ones(3, 6, CV_32F);

    //对a的第一列进行赋值

    //a.col(0) = c.col(0);

    c.col(0).copyTo(a.col(0));

    //将c的1-5列赋值给a

    //a.colRange(1, 6) = c;

    c.copyTo(a.colRange(1, 6));

这样再测试一下结果。试试看。

另外,colRange(start,end),包括左边界,不包括右边界,对rowRange同样适用。

 

版权声明:本文为CSDN博主「小黄人的banana」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/u014686356/article/details/65937750

 

      1. 数学矩阵运算

 

      1. 矩阵排序

https://blog.csdn.net/zfjBIT/article/details/88397910

  //sort int[9];

  int d1[9] = { 2, 4, 5, 2, 1, 8, 6, 7, 9 };

  cout << "d1[]: " << endl;

  for (int i = 0; i < 9; i++)

           cout << d1[i] << endl;

  sort(d1, d1+5);   // 注意: 参数如果不是指针变量的话 会报错 ,编译不过去

  cout << "d1[]: " << endl;

  for (int i = 0; i < 6; i++)

cout << d1[i] << endl;

Mat temp = srcImg.clone(); //图像复制

    int row = temp.rows; //取行

    int col = temp.cols;// 取列

---------------------------------------------------------------------------------------------

 

  Mat c1 = (Mat_<double>(3,3) << 1, 5 , 6 , 2 , 4, 2, 5, 9, 4);

  Mat c2(c1);

  sortIdx(c1, c2, SORT_EVERY_COLUMN + SORT_ASCENDING);

  cout << "c1: \n" << c1 << endl;

  cout << "c2: \n" << c2 << endl;

https://i-blog.csdnimg.cn/blog_migrate/78c71da1af18180b4e8a8fb530530bd3.jpeg

  //sort int[9];

  int d1[9] = { 2, 4, 5, 2, 1, 8, 6, 7, 9 };

  cout << "d1[]: " << endl;

  for (int i = 0; i < 9; i++)

      cout << d1[i] << endl;

  sort(d1, d1+5);   // 注意: 参数如果不是指针变量的话 会报错 ,编译不过去

  cout << "d1[]: " << endl;

  for (int i = 0; i < 6; i++)

      cout << d1[i] << endl;

 

矩阵排序

  int* c1begin = c1.ptr<int>(0);

  int* c1end = c1.ptr<int>(2);

  sort(c1begin, c1end+2);

  cout << endl<<"sort(c1begin, c1end+2)" << endl;

  cout << "c1: \n " << c1 << endl;

 

  sort(c1begin, c1end + 3);

  cout <<endl << "sort(c1begin, c1end+3)" << endl;

  cout << "c1: \n " << c1 << endl;

 

  sort(c1begin, c1end);

  cout << endl << "sort(c1begin, c1end)" << endl;

  cout << "c1: \n " << c1 << endl;

-========================================================================

#include <iostream> 

#include <opencv/cv.h> 

#include <opencv/highgui.h> 

using namespace std;

using namespace cv;

int main() 

    //cv::Mat testMat = cv::Mat::zeros ( 3, 3, CV_8UC1 );

    Mat dst;

    Mat testMat=(Mat_<int>(4,4) << 1,5,4,2,8,9,7,3,6,10,2,3,6,9,8,5);

 

    std::cout << "size of testMat: " << testMat.rows << " x " << testMat.cols << std::endl; 

    std::cout<<"testMat = "<<testMat<<std::endl; 

    //cv::Mat result = testMat.reshape ( 0, 1 ); 

 

    cv::Mat flat;

    testMat.reshape(1,1).copyTo(flat);

    cv::sort(flat,flat,CV_SORT_EVERY_ROW + CV_SORT_ASCENDING);

 

    flat.reshape(1,4).copyTo(dst);

    cout << " size of flat: " << flat.rows << " x " << flat.cols << std::endl; 

    cout << " size of reshaped dst: " << dst.rows << " x " << dst.cols << std::endl; 

    cout << "result = " << dst << std::endl; 

    waitKey(0); 

    system("pause"); 

    return 0; 

}

      1. 图像拷贝

图像拷贝有两种概念:

cv::Mat image;

1:浅拷贝

当图像之间进行赋值时,图像数据并未发生复制,两个对象指向同一块内存,改变图像2会影响图像1

cv::Mat img;

img = image;

2:深拷贝

当图像之间进行赋值时,图像数据发生复制,两个对象指向不同的内存,改变图像2不会影响图像1

cv::Mat img;

img.copyTo(image);

img = image.clone();

————————————————

版权声明:本文为CSDN博主「Mmagic1」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/Mmagic1/article/details/81808916

      1. OpenCV从Mat中提取某些行或列

Mat的rowRange和colRange可以获取某些范围内行或列的指针:

Mat::rowRange

Creates a matrix header for the specified row span.

C++: Mat Mat::rowRange(int startrow, int endrow) const

C++: Mat Mat::rowRange(const Range& r) const

Parameters:   

startrow – An inclusive 0-based start index of the row span.

endrow – An exclusive 0-based ending index of the row span.

r – Range structure containing both the start and the end indices.

The method makes a new header for the specified row span of the matrix. Similarly to Mat::row() and Mat::col() , this is an O(1) operation.

Mat::colRange

Creates a matrix header for the specified column span.

C++: Mat Mat::colRange(int startcol, int endcol) const

C++: Mat Mat::colRange(const Range& r) const

Parameters:   

startcol – An inclusive 0-based start index of the column span.

endcol – An exclusive 0-based ending index of the column span.

r – Range structure containing both the start and the end indices.

The method makes a new header for the specified column span of the matrix. Similarly to Mat::row() and Mat::col() , this is an O(1) operation.

由于这两个函数返回的是指向原矩阵内部位置的指针,所以最好再利用clone()函数进行数据拷贝创建新的矩阵,代码如下:

#include <opencv2/core/core.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <iostream>

using namespace cv;

using namespace std;

int main(){

          Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);

          cout << "Total matrix:" << endl;

          cout << C << endl;

          Mat row = C.rowRange(1,3).clone();

          cout << "Row range:" << endl;

          cout << row << endl;

          Mat col = C.colRange(1,3).clone();

          cout << "Col range:" << endl;

          cout << col << endl;

}

结果如下:

Total matrix

[0, -1, 0;

  -1, 5, -1;

  0, -1, 0]

Row range:

[-1, 5, -1;

  0, -1, 0]

Col range:

[-1, 0;

  5, -1;

  -1, 0]

————————————————

版权声明:本文为CSDN博主「大唐游子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/lichengyu/article/details/21407393

      1. 替换图像部分区域cvSetImageROI

有时候我们需要从一副图像中,获取感兴趣的区域ROI(region of interesting),将ROI区域裁剪成小图像,作为后期处理的输入。利用cvSetImageROI()函数便可以轻松搞定。

 

一、cvSetImageROI函数

 

功能

基于给定的矩形设置图像的ROI(感兴趣区域,region of interesting)

 

格式

void cvSetImageROI(IplImage* image,CvRect rect);

参数

image 图像头,待处理图像

rect ROI 矩形

例子

 

cvSetImageROI(image,cvRect(100,100,356,156)),(100,100)表示ROI区域的左上角坐标,356,156分别表示ROI区域的长宽。

 

说明

 

执行cvSetImageROI()之后显示image图像是只显示ROI标识的一部分,即改变了指针image,但是它仍旧保留有原来图像的信息,在执行这一句cvResetImageROI(image);之后,image指示原来的图像信息。

 

二、代码

 

#include <iostream>

#include <highgui.h>

 

using namespace std;

using namespace cv;

 

int main()

{

         IplImage *image = cvLoadImage("I:\\OpenCV Learning\\picture\\sumpalace.jpg");

 

         cvShowImage("image1",image);

         //将ROI区域图像保存在image中:左上角x、左上角y、矩形长、宽

         cvSetImageROI(image,cvRect(200,200,600,200));

         cvShowImage("imageROI",image);

         //执行cvSetImageROI()之后显示image图像是只显示ROI标识的一部分,即改变了指针image,

         //但是它仍旧保留有原来图像的信息,在执行这一句cvResetImageROI(image),之后,image指示原来的图像信息。

         cvResetImageROI(image);

         cvShowImage("image2",image);

         cvWaitKey(0);

 

         return 0;

}

————————————————

版权声明:本文为CSDN博主「生活没有if-else」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值