記錄C++的代碼

Vector


vector 複製

// 方法1
vector<int > v1(v2);//聲明

// 方法2 使用swap進行交換:
vector<int > v1();
v1.swap(v2);

// 方法3 使用函數assign進行賦值 【推薦】
vector<int > v1;//聲明v1
v1.assign(v2.begin(), v2.end());//將v2賦值給v1

// 方法4 循環賦值
vector<int >::iterator it;//聲明迭代器
for(it = v2.begin();it!=v2.end();++it){//遍歷v2,賦值給v1
     v1.push_back(it);
}

內存釋放

vector內存釋放需要使用下面語句
單獨的clear會導致內存泄漏

vector<T>().swap(x);
x.clear();

reserve 和resize

在Vector中,size是指容器當前擁有元素的個數,而capacity是指容器在必須分配新的存儲空間之前可以存放的元素總數。

reserve是容器預留空間,但在空間內不真正創建元素對象,所以在沒有添加新的對象之前,不能引用容器內的元素。此時size() != capacity()。
resize是改變容器的大小,且在創建對象,因此,調用這個函數之後,就可以引用容器內的對象了 此時size() == capacity()。

vector<int> myVec, myVec1;
myVec.reserve( 100 );     // 新元素還沒有構造, 此時不能用[]訪問元素, 但在VS中Release模式下可以
cout << "size = " << myVec.size() << " \t capacity =" << myVec.capacity() << "endl";
for (int i = 0; i < 100; i++ )
{ 
     myVec.push_back( i ); //新元素這時才構造
}
myVec1.resize( 102 );      // 用元素的默認構造函數構造了兩個新的元素
myVec1[100] = 1;           //直接操作新元素
myVec1[101] = 2;  
cout << "size = " << myVec1.size() << " \t capacity =" << myVec1.capacity() << "endl";
  • resize
 vector<int> vi={1,2,3}; 
 vi.resize(10, 9); 
 for(auto it=vi.begin();it!=vi.end();++it)  
        cout<<*it<<"  "; 
 // 輸出結果爲 1 2 3 9 9 9 9 9 9 9

OpenCV


下面幾篇blog可以參考

OpenCV for Matlab Users 2
OpenCV for Matlab Users 3
OpenCV for Matlab Users 4
OpenCV for Matlab Users 5


Mat

如果對Mat中的rows cols與height width感到迷惑,可以看看 這篇文章
簡單來說 在openCV新接口中(如 Mat, Range)是先rows 後cols
在老版本的接口類型中(如Point ,Rect) 是先寬後高 (x , y, w, h)

總的來說就是:
Mat類的rows(行)<==> IplImage結構體的heigh(高)<==> point.y
Mat類的cols(列) <==> IplImage結構體的width(寬)<==> point.x

// 初始化
Mat::zeros(thinIm.rows, thinIm.cols, CV_8U);
Mat depth(h, w, DataType<ushort>::type, cv::Scalar::all(0));
Mat zeroMatrix(Size(w, h), CV_8UC1, Scalar(0));

// 數組
float *data =  new float[rows*cols];
Mat mt(rows, cols, CV_32FC1, data);

//是否加載成功
if(img.empty()) return -1; 

//判斷是否有數據
if(!img.data) return -1;
  • Range()
    Range是爲了使opencv的使用更像Matlab而產生的。
    比如Range::all()其實就是Matlab裏的符號:或者…。
    而Range(a, b)其實就是Matlab中的a:b (包含a 不包括b
// 第0行至第99-->h, 
// 第50列至199-->w
// 返回的是視圖, 修改roi_img 依舊會改變 src_img
roi_img = src_img(Range(0,100),Range(50,200));

// Range是適用Mat類型的
// Rect是舊接口
Mat  B = A(Range::all(), Range(1, 300));
Mat  B = A(Rect(0,0,100,100));
  • Mat::setTo()
    setTo(Scalar s, mask)函數是將圖像設置爲某個值,第二個參數是mask,可以省略
// 將src的值全部設置成0
src.setTo(0)

// 將src中大於或者小於某個值的像素值設置爲指定的值 
src.setTo(0,src < 10);
bool matIsEqual(const cv::Mat mat1, const cv::Mat mat2) {
    if (mat1.empty() && mat2.empty()) {
        return true;
    }
    if (mat1.cols != mat2.cols || mat1.rows != mat2.rows || mat1.dims != mat2.dims||
        mat1.channels()!=mat2.channels()) {
        return false;
    }
    if (mat1.size() != mat2.size() || mat1.channels() != mat2.channels() || mat1.type() != mat2.type()) {
        return false;
    }
    int nrOfElements1 = mat1.total()*mat1.elemSize();
    if (nrOfElements1 != mat2.total()*mat2.elemSize()) return false;
    bool lvRet = memcmp(mat1.data, mat2.data, nrOfElements1) == 0;
    return lvRet;
}

Rect

// 定義
typedef Rect_<int> Rect;

Rect_(); // 形參列表爲空,即定義一個空窗口(默認值爲:x=y=width=height=0)

// 略過不提
Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
Rect_(const Rect_& r);
Rect_(const CvRect& r);

//org爲左上角起點, sz爲 (width, height)
Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);

// 由兩個點構成的矩形 左上和右下
Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);

常用函數

rect.area();     //返回rect的面積 5000  
rect.size();     //返回rect的尺寸 [50 × 100]  
rect.tl();       //返回rect的左上頂點的座標 [100, 50]  
rect.br();       //返回rect的右下頂點的座標 [150, 150]  
rect.width();    //返回rect的寬度 50  
rect.height();   //返回rect的高度 100  
rect.contains(Point(x, y));  //返回布爾變量,判斷rect是否包含Point(x, y)點  

//還可以求兩個矩形的交集和並集  
rect = rect1 & rect2;  
rect = rect1 | rect2;  

//還可以對矩形進行平移和縮放    
rect = rect + Point(-100, 100); //平移,也就是左上頂點的x座標-100,y座標+100  
rect = rect + Size(-100, 100);  //縮放,左上頂點不變,寬度-100,高度+100  

//還可以對矩形進行對比,返回布爾變量  
rect1 == rect2;  
rect1 != rect2;  

cvtColor 顏色空間轉換

cv::cvtColor(srcImage, dstImage, cv::COLOR_GRAY2BGR);
cv::cvtColor(srcImage, dstImage, cv::COLOR_BGR2GRAY);

convertTo 類型轉換

src.convertTo(dst, type, scale, shift)

 dst(i) = (type) scale* src(i) +shift
using namespace cv;

Mat mat, mat1;
mat = Mat::zeros(100,100,CV_32F);   // 得到一個浮點型的100*100的矩陣  
mat.convertTo(mat1, CV_8U);         // 把矩陣mat轉爲unsing char類型的矩陣

轉換爲浮點數需要加上scale,否則imshow顯示的時候會全白
for example, 255 becomes 255.0. But when you try `imshow’ the resulting image, the command expects all pixel values to be between 0.0 and 1.0.

mat.convertTo(output, CV_32F, 1.0/255.0)

findNonZero

Mat Im, NonZeroLoc;
findNonZero(Im, NonZeroLoc);
for (int i = 0; i < NonZeroLoc.total(); i++) {
    x = NonZeroLoc.at<Point>(i).x;                  // w  即cols
    y = NonZeroLoc.at<Point>(i).y;                  // h  即rows
}

得到的NonZeroLoc的遍歷結果,順序是先高後寬,可以想象成一條豎線由左向右移動,豎線上的點由上而下。

Matlab find

//Matlab: B(A<1)=0 
Mat B= A > 1;

// src2= (src1 <220 & src3 > 100);  // Error, 條件不能是兩個變量,即使大小相同  
src2= (src1 <220 & src1 > 100);     // 可以通過  
  • compare函數

void compare(InputArray src1, InputArray src2, OutputArray dst, int cmpop);

src1:原始圖像1(必須是單通道)或者一個數值,比如是一個Mat或者一個單純的數字n;
src2:原始圖像2(必須是單通道)或者一個數值,比如是一個Mat或者一個單純的數字n;
dst:結果圖像,類型是CV_8UC1,即單通道8位圖,大小和src1和src2中最大的那個一樣,比較結果爲真的地方值爲 255,否則爲0;
cmpop:操作類型,有以下幾種類型:
enum { CMP_EQ=0, //相等
CMP_GT=1, //大於
CMP_GE=2, //大於等於
CMP_LT=3, //小於
CMP_LE=4, //小於等於
CMP_NE=5 //不相等
};

// 從圖像中找出像素值爲50的像素點
cv::Mat result;  
cv::compare(image,50, result, cv::CMP_EQ);  

將多 channels轉成1 channels

static  Mat formatImageForPCA(const Mat &data, int rows)
{
    Mat dst(rows, 2, CV_32F);
    for (unsigned int i = 0; i < rows; i++)
    {
        Mat image_row = data.row(i).clone().reshape(1, 1);
        Mat row_i = dst.row(i);
        image_row.convertTo(row_i, CV_32F);
    }
    return dst;
}

Mat::type

Mat::type() 表示了矩陣中元素的類型以及矩陣的通道個數

    Mat a(n, n, src.type(), ptr, astep);

Class && 符號重載

實現 begin() 和 end() 可以進行for循環遍歷

class MyClass
{  
public:  
    MyClass():a{ 1,2,3,4,5 }   
    {  
    }  

    int* begin()//stl::begin模版調用  
    {   
        return a;  
    }   

    int* end() //stl::end模版可以調用  
    {   
        return a + sizeof(a)/sizeof(int);  
    } 

    // 重載[]操作符,作爲右值
    int& operator [](const int index);
    const int& operator [](const int index) const;
private:  
    int a[5];  
}; 

int main()
{
    MyClass myclass;
    for(int var : myclass)  
        cout << var << " ";  

    for(int i=0 ; i < 5; ++i)
        cout << myclass[i] << " "; 
}

常用函數

// 數字轉字符串
string str = std::to_string(42);
// 字符串分割函數  
std::vector<std::string> split(std::string str,std::string pattern)  
{  
    std::string::size_type pos;  
    std::vector<std::string> result;  
    str+=pattern;//擴展字符串以方便操作  
    int size=str.size();  

    for(int i=0; i<size; i++)  
    {  
        pos=str.find(pattern,i);  
        if(pos<size)  
        {  
            std::string s=str.substr(i,pos-i);  
            result.push_back(s);  
            i=pos+pattern.size()-1;  
        }  
    }  
    return result;  
}  

std::next_permutation

C++的全排列函數

min/max宏衝突

Windows.h中的 max min會和 std::max std::min衝突
解決方法有下面兩個

  1. 項目屬性 ——> C/C++ ——> 預處理器 ——> 預處理器定義 ——>加入NOMINMAX

  2. 加上下面預處理代碼

    
    #define NOMINMAX
    
    
    #undef max
    
    
    #undef min
    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章