zoukankan      html  css  js  c++  java
  • 【转载】cvReshape用法详解

    修改矩阵的形状——cvReshape的操作
    经实验表明矩阵操作的进行的顺序是:首先满足通道,然后满足列,最后是满足行。
     
    注意:1 这和Matlab是不同的,Matlab是行、列、通道的顺序;
                2.cvGetMat和cvReshape都只生成一个新的矩阵头,而数据都指向原来的地址,所以是两个矩阵共有一组数据,这一点在使用中要注意,原来的数据撤消是否会影响后生成的矩阵的使用;
               3.cvReshape是按行形成向量,如果想按列形成向量,就先调用cvTranspose对矩阵进行转置,再调用cvReshape;
              4.同样大小的IplImage和CvMat,IplImage->widthStep不等于CvMat->step???(待验证)

    我们在此举例如下:
    对于一通道:
    // 1 channel
    CvMat *mat, mathdr;
    double data[] = { 11, 12, 13, 14,
    21, 22, 23, 24,
    31, 32, 33, 34 };
    CvMat* orig = &cvMat( 3, 4, CV_64FC1, data );
    //11 12 13 14
    //21 22 23 24
    //31 32 33 34
    mat = cvReshape( orig, &mathdr, 1, 1 ); // new_ch, new_rows
    cvDoubleMatPrint( mat ); // above
    // 11 12 13 14 21 22 23 24 31 32 33 34
    mat = cvReshape( mat, &mathdr, 1, 3 ); // new_ch, new_rows
    cvDoubleMatPrint( mat ); // above
    //11 12 13 14
    //21 22 23 24
    //31 32 33 34
    mat = cvReshape( orig, &mathdr, 1, 12 ); // new_ch, new_rows
    cvDoubleMatPrint( mat ); // above
    // 11
    // 12
    // 13
    // 14
    // 21
    // 22
    // 23
    // 24
    // 31
    // 32
    // 33
    // 34
    mat = cvReshape( mat, &mathdr, 1, 3 ); // new_ch, new_rows
    cvDoubleMatPrint( mat ); // above
    //11 12 13 14
    //21 22 23 24
    //31 32 33 34
    mat = cvReshape( orig, &mathdr, 1, 2 ); // new_ch, new_rows
    cvDoubleMatPrint( mat ); // above
    //11 12 13 14 21 22
    //23 24 31 32 33 34
    mat = cvReshape( mat, &mathdr, 1, 3 ); // new_ch, new_rows
    cvDoubleMatPrint( mat ); // above
    //11 12 13 14
    //21 22 23 24
    //31 32 33 34
    mat = cvReshape( orig, &mathdr, 1, 6 ); // new_ch, new_rows
    cvDoubleMatPrint( mat ); // above
    // 11 12
    // 13 14
    // 21 22
    // 23 24
    // 31 32
    // 33 34
    mat = cvReshape( mat, &mathdr, 1, 3 ); // new_ch, new_rows
    cvDoubleMatPrint( mat ); // above
    //11 12 13 14
    //21 22 23 24
    //31 32 33 34
    // Use cvTranspose and cvReshape( mat, &mathdr, 1, 2 ) to get
    // 11 23
    // 12 24
    // 13 31
    // 14 32
    // 21 33
    // 22 34
    // Use cvTranspose again when to recover

    对于三通道
    // 3 channels
    CvMat mathdr, *mat;
    double data[] = { 111, 112, 113, 121, 122, 123,
    211, 212, 213, 221, 222, 223 };
    CvMat* orig = &cvMat( 2, 2, CV_64FC3, data );
    //(111,112,113) (121,122,123)
    //(211,212,213) (221,222,223)
    mat = cvReshape( orig, &mathdr, 3, 1 ); // new_ch, new_rows
    cv3DoubleMatPrint( mat ); // above
    // (111,112,113) (121,122,123) (211,212,213) (221,222,223)
    // concatinate in column first order
    mat = cvReshape( orig, &mathdr, 1, 1 );// new_ch, new_rows
    cvDoubleMatPrint( mat ); // above
    // 111 112 113 121 122 123 211 212 213 221 222 223
    // concatinate in channel first, column second, row third
    mat = cvReshape( orig, &mathdr, 1, 3); // new_ch, new_rows
    cvDoubleMatPrint( mat ); // above
    //111 112 113 121
    //122 123 211 212
    //213 221 222 223
    // channel first, column second, row third
    mat = cvReshape( orig, &mathdr, 1, 4 ); // new_ch, new_rows
    cvDoubleMatPrint( mat ); // above
    //111 112 113
    //121 122 123
    //211 212 213
    //221 222 223
    // channel first, column second, row third
    // memorize this transform because this is useful to
    // add (or do something) color channels
    CvMat* mat2 = cvCreateMat( mat->cols, mat->rows, mat->type );
    cvTranspose( mat, mat2 );
    cvDoubleMatPrint( mat2 ); // above
    //111 121 211 221
    //112 122 212 222
    //113 123 213 223
    cvReleaseMat( &mat2 );

    计算色彩距离
    我们要计算img1,img2的每个像素的距离,用dist表示,定义如下
    IplImage *img1 = cvCreateImage( cvSize(w,h), IPL_DEPTH_8U, 3 );
    IplImage *img2 = cvCreateImage( cvSize(w,h), IPL_DEPTH_8U, 3 );
    CvMat *dist = cvCreateMat( h, w, CV_64FC1 );
    比较笨的思路是:cvSplit->cvSub->cvMul->cvAdd
    代码如下:
    IplImage *img1B = cvCreateImage( cvGetSize(img1), img1->depth, 1 );
    IplImage *img1G = cvCreateImage( cvGetSize(img1), img1->depth, 1 );
    IplImage *img1R = cvCreateImage( cvGetSize(img1), img1->depth, 1 );
    IplImage *img2B = cvCreateImage( cvGetSize(img1), img1->depth, 1 );
    IplImage *img2G = cvCreateImage( cvGetSize(img1), img1->depth, 1 );
    IplImage *img2R = cvCreateImage( cvGetSize(img1), img1->depth, 1 );
    IplImage *diff = cvCreateImage( cvGetSize(img1), IPL_DEPTH_64F, 1 );
    cvSplit( img1, img1B, img1G, img1R );
    cvSplit( img2, img2B, img2G, img2R );
    cvSub( img1B, img2B, diff );
    cvMul( diff, diff, dist );
    cvSub( img1G, img2G, diff );
    cvMul( diff, diff, diff);
    cvAdd( diff, dist, dist );
    cvSub( img1R, img2R, diff );
    cvMul( diff, diff, diff );
    cvAdd( diff, dist, dist );
    cvReleaseImage( &img1B );
    cvReleaseImage( &img1G );
    cvReleaseImage( &img1R );
    cvReleaseImage( &img2B );
    cvReleaseImage( &img2G );
    cvReleaseImage( &img2R );
    cvReleaseImage( &diff );

    比较聪明的思路是
    int D = img1->nChannels; // D: Number of colors (dimension)
    int N = img1->width * img1->height; // N: number of pixels
    CvMat mat1hdr, *mat1 = cvReshape( img1, &mat1hdr, 1, N ); // N x D(colors)
    CvMat mat2hdr, *mat2 = cvReshape( img2, &mat2hdr, 1, N ); // N x D(colors)
    CvMat diffhdr, *diff = cvCreateMat( N, D, CV_64FC1 ); // N x D, temporal buff
    cvSub( mat1, mat2, diff );
    cvMul( diff, diff, diff );
    dist = cvReshape( dist, &disthdr, 1, N ); // nRow x nCol to N x 1
    cvReduce( diff, dist, 1, CV_REDUCE_SUM ); // N x D to N x 1
    dist = cvReshape( dist, &disthdr, 1, img1->height ); // Restore N x 1 to nRow x nCol
    cvReleaseMat( &diff );
     

     

     

    #pragma comment( lib, "cxcore.lib" )
    #include "cv.h"
    #include <stdio.h>
    int main()
    {
    CvMat* mat = cvCreateMat(3,3,CV_32FC1);
    cvZero(mat);//将矩阵置0
    //为矩阵元素赋值
    CV_MAT_ELEM( *mat, float, 0, 0 ) = 1.f;
    CV_MAT_ELEM( *mat, float, 0, 1 ) = 2.f;
    CV_MAT_ELEM( *mat, float, 0, 2 ) = 3.f;
    CV_MAT_ELEM( *mat, float, 1, 0 ) = 4.f;
    CV_MAT_ELEM( *mat, float, 1, 1 ) = 5.f;
    CV_MAT_ELEM( *mat, float, 1, 2 ) = 6.f;
    CV_MAT_ELEM( *mat, float, 2, 0 ) = 7.f;
    CV_MAT_ELEM( *mat, float, 2, 1 ) = 8.f;
    CV_MAT_ELEM( *mat, float, 2, 2 ) = 9.f;
    //获得矩阵元素(0,2)的值
    float *p = (float*)cvPtr2D(mat, 0, 2);
    printf("%f/n",*p);
    return 0;
    }

  • 相关阅读:
    判别模型、生成模型与朴素贝叶斯方法
    git的安装已经连github
    uva 10061 How many zero's and how many digits ?
    Java菜鸟学习笔记()--面向对象篇(七):Wrapper Class包装类
    丁香园技术负责人冯大辉近日在知乎上披露了当年共同创办阿里巴巴的18个合伙人的近况:
    不用派生CTreeCtrl不用繁琐的过程 教你如何让CTreeCtrl的每一项有ToolTip提示
    数据结构排序系列详解之三 冒泡排序
    HDU 4612 (13年多校第二场1002)无向图缩点,有重边
    Mac下cocos2dx3.1用Cocos IDE写的Lua binding篇01
    SECURITY_ATTRIBUTES 设置低权限
  • 原文地址:https://www.cnblogs.com/jiayouwyhit/p/3045761.html
Copyright © 2011-2022 走看看