C++ opencv的一些基础知识

2023-11-15

一.基础知识 

1.cv::mat type返回数字对应的类型

 C1, C2, C3, C4 指的是通道(Channel)数,比如3通道的float 32:

cv::Mat M5 = cv::Mat::zeros(2, 3, CV_32FC(3));

2.at方法数据类型

知道通道数和每个通道数据类型的情况下,指定给 at 方法的数据类型如下表所示:

#include<opencv2/opencv.hpp>
#include<iostream>
#include<string>
using namespace std;


void debug_opencv(){
    cv::Mat M1 = cv::Mat::zeros(2, 3, CV_32F);//CV_32F等效于CV_32FC(1)
    cout<<"M1.type():"<<M1.type()<<endl;
    cout<<"M1:"<<M1<<endl;


    cv::Mat M2 = cv::Mat::zeros(2, 3, CV_32FC(1));
    cout<<"before M2.type()"<<M2.type()<<endl;
    cout<<"before M2:"<<M2<<endl;
    for(int i = 0; i < M2.rows; i++){
        for(int j = 0; j < M2.cols; j++){
            for(int c = 0; c < M2.channels(); c++){
                M2.at<cv::Vec<float, 1>>(i, j)[c] = float(i + j + c);
            }
        }
    }
    cout<<"after M2.type()"<<M2.type()<<endl;
    cout<<"after M2"<<M2<<endl;
    //Vec2f表示的是2通道float类型的
    cv::Mat M3 = cv::Mat::zeros(2, 3, CV_32FC(2));
    cout<<"before M3.type()"<<M3.type()<<endl;
    cout<<"before M3:"<<M3<<endl;
    for(int i = 0; i < M3.rows; i++){
        for(int j = 0; j < M3.cols; j++){
            for(int c = 0; c < M3.channels(); c++){
//                if(c == 0){
//                    cout<<"float(i + j + c):"<<float(i + j + c)<<",";
//                }
                M3.at<cv::Vec2f>(i, j)[c] = float(i + j + c);
            }
        }
    }
    cout<<"after M3.type()"<<M3.type()<<endl;
    cout<<"after M3:"<<M3<<endl;
    //[0, 1, 1, 2, 2, 3;
    // 1, 2, 2, 3, 3, 4]

    //Vec3f表示的是3通道float类型的
    cv::Mat M5 = cv::Mat::zeros(2, 3, CV_32FC(3));
    cout<<"before M5.type()"<<M5.type()<<endl;
    cout<<"before M5:"<<M5<<endl;
    for(int i = 0; i < M5.rows; i++){
        for(int j = 0; j < M5.cols; j++){
            for(int c = 0; c < M5.channels(); c++){
//                if(c == 0){
//                    cout<<"float(i + j + c):"<<float(i + j + c)<<",";
//                }
                M5.at<cv::Vec3f>(i, j)[c] = float(i + j + c);
            }
        }
    }
    cout<<"M5:"<<M5<<endl;
    //[0, 1, 2, 1, 2, 3, 2, 3, 4;
    //1, 2, 3, 2, 3, 4, 3, 4, 5]
}
int main(){  
    debug_opencv();
    return 0;
}   

 

3.mat赋值

    cv::Mat trans_mat(2, 3, CV_32FC(1), cv::Scalar(1));
    cout<<"==trans_mat.size:"<<trans_mat.size<<endl;
    cout<<"==trans_mat:"<<trans_mat<<endl;

    cv::Mat affine_matrix =
            (cv::Mat_<float>(3, 3) << trans_mat.at<float>(0), trans_mat.at<float>(1), trans_mat.at<float>(2),
                                      trans_mat.at<float>(3), trans_mat.at<float>(4), trans_mat.at<float>(5), 
                                      0, 0, 1);    
    cout<<"==affine_matrix:"<<affine_matrix<<endl;

二.一些api

1.构建矩阵

#include "iostream"
#include <opencv2/opencv.hpp>
#include "opencv2/dnn/dnn.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include <vector>
using namespace std;

typedef cv::Vec<double, 5> Vec5d;

void scalar_demo4(){
    cv::Mat M = cv::Mat::zeros(2, 3, CV_64FC(5));
    cout<<"==M.channels():"<<M.channels()<<endl;
    cout<<"==before M:"<<M<<endl;
    for(int i = 0; i < M.rows; i++){
        for(int j = 0; j < M.cols; j++){
            for(int c = 0; c < M.channels(); c++){
                M.at<Vec5d>(i,j)[c] = c * 0.01;
            }
        }
    }
    cout<<"==after M:"<<M<<endl;
}


int main(int argc ,char** argv)
{
    cout<<CV_VERSION<<endl;
    scalar_demo4();
    return 0;
}

2.构建矩阵与访问某个像素值

#include "iostream"
#include <opencv2/opencv.hpp>
#include "opencv2/dnn/dnn.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include <vector>
using namespace std;


cv::Mat scalar_demo1(){
    cv::Mat M(4,4,CV_32FC2,cv::Scalar(1,3));
    cout<<"before M"<<M<<endl;
    return M;
}
void scalar_demo2(){
    cv::Mat M(4,4,CV_32FC3,cv::Scalar(1,2,3));
    cout<<M<<endl;
    cout<<"==M.type():"<<M.type()<<endl;
    cout<<"==M.channels():"<<M.channels()<<endl;
    cout<<"==M.rows:"<<M.rows<<endl;
    cout<<"==M.cols:"<<M.cols<<endl;
    //获取矩阵size 只显示h w 不显示channel
    cv::Size size_ = M.size();
    cout<<"==size_:"<<size_<<endl;
    //获取面积
    int area = M.total();
    cout<<"==area:"<<area<<endl;
    //获取维数
    int dims = M.dims;
    cout<<"==dims:"<<dims<<endl;
    //访问某个值 利用成员函数at 先获取坐标处向量 再根据索引获取值
    cv::Vec3f pixel_vector1 = M.at<cv::Vec3f>(0, 0);//获取y=0 x=0处向量
    cout<<"==pixel_vector1:"<<pixel_vector1<<endl;
    cout<<"==pixel_vector1[1]:"<<pixel_vector1[1]<<endl;

    //访问某个值 利用成员函数ptr
    auto* ptr1 = M.ptr<cv::Vec3f>(0);//获取y=0处地址
    cv::Vec3f pixel_vector2 = ptr1[0];// 再来x=0处获取向量
    cout<<"==ptr1:"<<ptr1<<endl;
    cout<<"==*ptr1:"<<*ptr1<<endl;//得到首地址向量
    cout<<"==pixel_vector2:"<<pixel_vector2<<endl;
    cout<<"==pixel_vector2[1]:"<<pixel_vector2[1]<<endl;

    //访问某个值用: 利用成员变量data和step, step[0]表示每一行占的字节,step[1]表示每个元素占的字节
    int y = 0, x = 0;
    auto* ptr2 = (cv::Vec3f* )(M.data + y * M.step[0] + x * M.step[1]);//获取y=0 x=0处向量地址
    cout<<"==ptr2:"<<ptr2<<endl;
    cout<<"==*ptr2:"<<*ptr2<<endl; //得到首地址向量
    cv::Vec3f pixel_vector3 = ptr2[0];
    cout<<"==pixel_vector3:"<<pixel_vector2<<endl;
    cout<<"==pixel_vector2[1]:"<<pixel_vector2[1]<<endl;
}
void scalar_demo3(){
    cv::Mat M(4,4,CV_32FC4,cv::Scalar(1,2,3));
    cout<<M<<endl;
    cout<<"==M.type():"<<M.type()<<endl;
}


int main(int argc ,char** argv)
{
    cout<<CV_VERSION<<endl;
    cv::Mat M = scalar_demo1();
    cout<<"after M"<<M<<endl;
    cout<<"**********************************"<<endl;
    scalar_demo2();
    cout<<"**********************************"<<endl;
    scalar_demo3();
    return 0;
}

 CV_32F表示每个元素的值的类型为32位浮点数,C2表示通道数为2,Scalar(1,2,3)表示对矩阵每个元素都赋值为(1,2,3),第一个通道中的值都是1,第二个通道中的值都是2,第三个通道中的值都是3.

3.split与merge

#include "iostream"
#include <opencv2/opencv.hpp>
#include "opencv2/dnn/dnn.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include <vector>
using namespace std;

typedef cv::Vec<double, 5> Vec5d;

void scalar_demo4(){
    cv::Mat M = cv::Mat::zeros(2, 3, CV_64FC(5));
    cout<<"==M.channels():"<<M.channels()<<endl;
    cout<<"==before M:"<<M<<endl;
    for(int i = 0; i < M.rows; i++){
        for(int j = 0; j < M.cols; j++){
            for(int c = 0; c < M.channels(); c++){
                M.at<Vec5d>(i,j)[c] = c * 0.01;
            }
        }
    }
    cout<<"==after M:"<<M<<endl;
    //split 拆分通道
    vector<cv::Mat> channels;
    cv::split(M, channels);
    cout<<"==channels[0]:"<<channels[0]<<endl;
    cout<<"==channels[1]:"<<channels[1]<<endl;
    cout<<"==channels[2]:"<<channels[2]<<endl;
    cout<<"==channels[3]:"<<channels[3]<<endl;
    cout<<"==channels[4]:"<<channels[4]<<endl;

    //Merge合并
    cv::Mat newchannels[] = {channels[4], channels[3], channels[2], channels[1], channels[0]};
    cv::Mat MergeM;
    cv::merge(newchannels, sizeof(newchannels)/ sizeof(newchannels[0]), MergeM);
    cout<<"==merge M:"<<MergeM<<endl;
}



int main(int argc ,char** argv)
{

    cout<<CV_VERSION<<endl;
    scalar_demo4();
    return 0;
}

4.查看视频帧与统计时间

python:

#!/usr/bin/env python

import cv2
import time

if __name__ == '__main__' :

    # Start default camera
    video = cv2.VideoCapture(0);
    
    # Find OpenCV version
    (major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.')
    print(major_ver, minor_ver, subminor_ver)
    # With webcam get(CV_CAP_PROP_FPS) does not work.
    # Let's see for ourselves.
    
    if int(major_ver)  < 3 :
        fps = video.get(cv2.cv.CV_CAP_PROP_FPS)
        print("Frames per second using video.get(cv2.cv.CV_CAP_PROP_FPS): {0}".format(fps))
    else :
        fps = video.get(cv2.CAP_PROP_FPS)
        print("Frames per second using video.get(cv2.CAP_PROP_FPS) : {0}".format(fps))
    

    # Number of frames to capture
    num_frames = 120
    
    
    print("Capturing {0} frames".format(num_frames))

    # Start time
    start = time.time()
    
    # Grab a few frames
    for i in range(0, num_frames):
        ret, frame = video.read()

    
    # End time
    end = time.time()

    # Time elapsed
    seconds = end - start
    print("Time taken : {0} seconds".format(seconds))

    # Calculate frames per second
    fps = num_frames / seconds
    print("Estimated frames per second : {0}".format(fps))

    # Release video
    video.release()


c++:

#include <opencv2/opencv.hpp>
#include "time.h"
int main(){
    // Start default camera
    cv::VideoCapture video(0);
    // With webcam get(CV_CAP_PROP_FPS) does not work.
    // Let's see for ourselves.
    std::cout << CV_VERSION<<std::endl;
    double fps = video.get(cv::CAP_PROP_FPS);
    // If you do not care about backward compatibility
    // You can use the following instead for OpenCV 3
    // double fps = video.get(CAP_PROP_FPS);
    std::cout << "Frames per second using video.get(CV_CAP_PROP_FPS) : " << fps << std::endl;

    int num_frames = 120;

    // Start and end times
    time_t start, end;
    // Variable for storing video frames
    cv::Mat frame;

    std::cout << "Capturing " << num_frames << " frames" << std::endl ;

    // Start time
    time(&start);
    // Grab a few frames
    for(int i = 0; i < num_frames; i++)
    {
        video >> frame;
    }
    // End Time
    time(&end);
    // Time elapsed
    double seconds = difftime (end, start);
    std::cout << "Time taken : " << seconds << " seconds" << std::endl;

    // Calculate frames per second
    fps  = num_frames / seconds;
    std::cout << "Estimated frames per second : " << fps << std::endl;

    // Release video
    video.release();
    return  0;
}

5.仿射变换

//
// Created by fzh on 2021/6/22.
//

//#include <pybind11/numpy.h>
//#include <a.h>
//#include <b.h>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <string>
#include <algorithm>
#include <vector>
#include <memory>

typedef cv::Vec<double, 5> Vec5d;
using namespace std;

cv::Mat pre_process(const cv::Mat &image, std::vector<float> &ratio) {
    // normalize
    //debug
    int input_width_ = 800, input_height_ = 1333;
    cv::Scalar mean_ = cv::Scalar(111.522);
    cv::Scalar std_ = cv::Scalar(1./38.877);

    cv::Mat normed_image;
    float img_height = image.rows;
    float img_width = image.cols;
    float max_long_edge = std::max(input_width_, input_height_);
    float max_short_edge = std::min(input_width_, input_height_);
    float scale_factor =
            std::min(max_long_edge / std::max(img_height, img_width),
                     max_short_edge / std::min(img_height, img_width));
    // int new_h = scale_factor * img_height;
    // int new_w = scale_factor * img_width;
    ratio.push_back(scale_factor);
    ratio.push_back(scale_factor);

    cv::Mat transform_mat =
            (cv::Mat_<float>(2, 3) << scale_factor, 0, 0, 0, scale_factor, 0);
    cout<<"transform_mat:"<<transform_mat<<endl;
    cv::Mat resized_img;
    cv::warpAffine(image, resized_img, transform_mat,
                   cv::Size(input_width_, input_height_), cv::INTER_LINEAR,
                   cv::BORDER_CONSTANT, cv::Scalar(127));
    // cv::resize(image, resized_img, cv::Size(input_width_, input_height_));

    // img.convertTo(normed_im, CV_32FC3, 1 / 255.0);
    cv::imwrite("warp_resize_img.jpg", resized_img);
    resized_img.convertTo(normed_image, CV_32FC1);
    // cv::Mat mean(input_height_, input_width_, CV_32FC3, s);
    normed_image -= mean_;
    normed_image = normed_image.mul(std_);
    return normed_image;
}
void debug_preprocess(){
    cv::Mat img = cv::imread("/2.jpg", 0);
    vector<float> ratio;
    std::cout<<"before img h:"<<img.rows<<std::endl;
    std::cout<<"before img w:"<<img.cols<<std::endl;
    pre_process(img, ratio);
    for(int i=0; i<ratio.size(); i++){
        cout<<"ratio[i]:"<<ratio[i]<<endl;
    }
}
int main(int argc, char** argv)
{
    debug_preprocess();
    return 0;
}

6.cv::minMaxLoc获取feature map最大值索引

python代码:

from __future__ import division
import cv2
import time
import numpy as np

protoFile = "./hand/pose_deploy.prototxt"
weightsFile = "./hand/pose_iter_102000.caffemodel"
nPoints = 22
POSE_PAIRS = [[0, 1], [1, 2], [2, 3], [3, 4],
              [0, 5], [5, 6], [6, 7], [7, 8],
              [0, 9], [9, 10], [10, 11], [11, 12],
              [0, 13], [13, 14], [14, 15], [15, 16],
              [0, 17], [17, 18], [18, 19], [19, 20]]
net = cv2.dnn.readNetFromCaffe(protoFile, weightsFile)

frame = cv2.imread("./right-frontal.jpg")
frameCopy = np.copy(frame)
frameWidth = frame.shape[1]
frameHeight = frame.shape[0]
aspect_ratio = frameWidth / frameHeight

threshold = 0.1

start_time = time.time()
# input image dimensions for the network
inHeight = 368
inWidth = int(((aspect_ratio * inHeight) * 8) // 8)
print(inHeight, inWidth)
# frame = cv2.resize(frame, (inWidth, inHeight))
# print(frame.shape)
inpBlob = cv2.dnn.blobFromImage(frame, 1.0 / 255, (inWidth, inHeight), (0, 0, 0), swapRB=False, crop=False)

net.setInput(inpBlob)
print(inpBlob.shape)
output = net.forward()
print("time taken by network : {:.3f}".format(time.time() - start_time))

# Empty list to store the detected keypoints
points = []

for i in range(nPoints):
    # confidence map of corresponding body's part.
    probMap = output[0, i, :, :]
    probMap = cv2.resize(probMap, (frameWidth, frameHeight))
    # Find global maxima of the probMap.
    minVal, prob, minLoc, point = cv2.minMaxLoc(probMap)

    if prob > threshold:
        cv2.circle(frameCopy, (int(point[0]), int(point[1])), 8, (0, 255, 255), thickness=-1, lineType=cv2.FILLED)
        cv2.putText(frameCopy, str(i), (int(point[0]), int(point[1])), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2,
                    lineType=cv2.LINE_AA)

        # Add the point to the list if the probability is greater than the threshold
        points.append((int(point[0]), int(point[1])))
    else:
        points.append(None)

# Draw Skeleton
for pair in POSE_PAIRS:
    partA = pair[0]
    partB = pair[1]

    if points[partA] and points[partB]:
        cv2.line(frame, points[partA], points[partB], (0, 255, 255), 2)
        cv2.circle(frame, points[partA], 8, (0, 0, 255), thickness=-1, lineType=cv2.FILLED)
        cv2.circle(frame, points[partB], 8, (0, 0, 255), thickness=-1, lineType=cv2.FILLED)

cv2.imshow('Output-Keypoints', frameCopy)
cv2.imshow('Output-Skeleton', frame)

cv2.imwrite('Output-Keypoints.jpg', frameCopy)
cv2.imwrite('Output-Skeleton.jpg', frame)

print("Total time taken : {:.3f}".format(time.time() - start_time))

cv2.waitKey(0)
    cv::Mat probMap = (cv::Mat_<float>(3, 3) <<0,10,0,1,2,3,4,5,6);
    cv::Point maxLoc;
    double prob;
    cout<<"probMap:"<<probMap<<endl;
    cv::minMaxLoc(probMap, 0, &prob, 0, &maxLoc);
    cout<<"maxLoc.x:"<<maxLoc.x<<endl;
    cout<<"maxLoc.y"<<maxLoc.y<<endl;

c++代码:

#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

const int POSE_PAIRS[20][2] =
        {
                {0,1}, {1,2}, {2,3}, {3,4},         // thumb
                {0,5}, {5,6}, {6,7}, {7,8},         // index
                {0,9}, {9,10}, {10,11}, {11,12},    // middle
                {0,13}, {13,14}, {14,15}, {15,16},  // ring
                {0,17}, {17,18}, {18,19}, {19,20}   // small
        };

std::string protoFile = "/home/momenta/AI/c++_project_test/hand/pose_deploy.prototxt";
std::string weightsFile = "/home/momenta/AI/c++_project_test/hand/pose_iter_102000.caffemodel";

int nPoints = 22;

int main(int argc, char **argv)
{

    std::cout << "USAGE : ./handPoseImage <imageFile> " << std::endl;

    std::string imageFile = "/home/momenta/AI/c++_project_test/right-frontal.jpg";
    // Take arguments from commmand line
    if (argc == 2)
    {
        imageFile = argv[1];
    }

    float thresh = 0.1;

    cv::Mat frame = cv::imread(imageFile);
    cv::Mat frameCopy = frame.clone();
    int frameWidth = frame.cols;
    int frameHeight = frame.rows;

    float aspect_ratio = frameWidth/(float)frameHeight;
    int inHeight = 368;
    int inWidth = (int(aspect_ratio*inHeight) * 8) / 8;

    std::cout << "framenWidth = " << frameWidth << " ; frameHeight = " << frameHeight << std::endl;
    std::cout << "inWidth = " << inWidth << " ; inHeight = " << inHeight << std::endl;

    double start_time = (double) cv::getTickCount();
    cv::dnn::Net net = cv::dnn::readNetFromCaffe(protoFile, weightsFile);

    cv::Mat inpBlob = cv::dnn::blobFromImage(frame, 1.0 / 255, cv::Size(inWidth, inHeight), cv::Scalar(0, 0, 0), false, false);
    std::cout<<"inpBlob.dims:"<<inpBlob.dims<<std::endl;
    std::cout<<"inpBlob.size:"<<inpBlob.size<<std::endl;
    net.setInput(inpBlob);

    cv::Mat output = net.forward();
    std::cout<<"output.size:"<<output.size<<std::endl;
    int H = output.size[2];
    int W = output.size[3];

    // find the position of the body parts
    std::vector<cv::Point> points(nPoints);
    for (int i=0; i < nPoints; i++)
    {
        // Probability map of corresponding body's part.
        cv::Mat probMap(H, W, CV_32F, output.ptr(0, i));
        std::cout<<"probMapt.size:"<<probMap.size<<std::endl;
        resize(probMap, probMap, cv::Size(frameWidth, frameHeight));

        cv::Point maxLoc;
        double prob;
        cv::minMaxLoc(probMap, 0, &prob, 0, &maxLoc);
//        std::cout<<"prob:"<<prob<<std::endl;
        if (prob > thresh)
        {
//            std::cout<<"(int)maxLoc.x:"<<(int)maxLoc.x<<std::endl;
//            std::cout<<"(int)maxLoc.y:"<<(int)maxLoc.y<<std::endl;
//            circle(frame, cv::Point((int)maxLoc.x, (int)maxLoc.y), 8, Scalar(0,255,255), -1);
            cv::putText(frame, std::to_string(i), cv::Point((int)maxLoc.x, (int)maxLoc.y), cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(0, 0, 255), 2);

        }
        points[i] = maxLoc;
    }

    int nPairs = sizeof(POSE_PAIRS)/sizeof(POSE_PAIRS[0]);

    for (int i = 0; i < nPairs; i++)
    {
        // lookup 2 connected body/hand parts
        cv::Point2f partA = points[POSE_PAIRS[i][0]];
        cv::Point2f partB = points[POSE_PAIRS[i][1]];

        if (partA.x<=0 || partA.y<=0 || partB.x<=0 || partB.y<=0)
            continue;

        line(frame, partA, partB, cv::Scalar(0,255,255), 8);
        circle(frame, partA, 8, cv::Scalar(0,0,255), -1);
        circle(frame, partB, 8, cv::Scalar(0,0,255), -1);
    }

    double cost_time = ((double)cv::getTickCount() - start_time)/cv::getTickFrequency();
    std::cout << "Time Taken = " << cost_time << std::endl;
    cv::imwrite("Output-Skeleton.jpg", frame);

    return 0;
}

7.cv::projectPoints 通过旋转向量,平移向量与相机坐标系3d点算出投影2d点

有两种解法一个是标题所述,一个是用旋转向量计算出旋转矩阵,用外参和内参变化计算出投影2d点.

python:

#!/usr/bin/env python

import cv2
import numpy as np

def method_one(rotation_matrix, translation_vector, camera_matrix, dist_coeffs, start_point):
    cam_3d = rotation_matrix.dot(start_point.reshape(-1, 1)) + translation_vector
    print('==cam_3d:', cam_3d)

    def camera_to_img2d(x, K, Kd):
        """x(3, N)"""
        x[0:2, :] = x[0:2, :] / x[2, :]  # (2, N)
        r = x[0, :] * x[0, :] + x[1, :] * x[1, :]  # x^2 + y^2 (N, )
        x[0, :] = x[0, :] * (1 + Kd[0] * r + Kd[1] * r * r + Kd[4] * r * r * r) + 2 * Kd[2] * x[0, :] * x[1, :] + Kd[
            3] * (
                          r + 2 * x[0, :] * x[0, :])
        x[1, :] = x[1, :] * (1 + Kd[0] * r + Kd[1] * r * r + Kd[4] * r * r * r) + 2 * Kd[3] * x[0, :] * x[1, :] + Kd[
            2] * (
                          r + 2 * x[1, :] * x[1, :])
        x[0, :] = K[0, 0] * x[0, :] + K[0, 1] * x[1, :] + K[0, 2]
        x[1, :] = K[1, 0] * x[0, :] + K[1, 1] * x[1, :] + K[1, 2]
        return x

    _2d = camera_to_img2d(cam_3d, camera_matrix, dist_coeffs)
    # print('==_2d:', _2d)
    return _2d
def method_two(rotation_vector, translation_vector, camera_matrix, dist_coeffs, start_point):
    # Project a 3D point (0, 0, 1000.0) onto the image plane.
    # We use this to draw a line sticking out of the nose
    (nose_end_point2D, jacobian) = cv2.projectPoints(start_point, rotation_vector, translation_vector, camera_matrix, dist_coeffs)
    # print('==nose_end_point2D:', nose_end_point2D)
    return nose_end_point2D

def main():
    # Read Image
    im = cv2.imread("headPose.jpg")
    size = im.shape

    # 2D image points. If you change the image, you need to change vector
    image_points = np.array([
        (359, 391),  # Nose tip
        (399, 561),  # Chin
        (337, 297),  # Left eye left corner
        (513, 301),  # Right eye right corne
        (345, 465),  # Left Mouth corner
        (453, 469)  # Right mouth corner
    ], dtype=np.float32)

    # 3D model points.
    model_points = np.array([
        (0.0, 0.0, 0.0),  # Nose tip
        (0.0, -330.0, -65.0),  # Chin
        (-225.0, 170.0, -135.0),  # Left eye left corner
        (225.0, 170.0, -135.0),  # Right eye right corne
        (-150.0, -150.0, -125.0),  # Left Mouth corner
        (150.0, -150.0, -125.0)  # Right mouth corner

    ])

    # Camera internals
    focal_length = size[1]
    center = (size[1] / 2, size[0] / 2)
    camera_matrix = np.array(
        [[focal_length, 0, center[0]],
         [0, focal_length, center[1]],
         [0, 0, 1]], dtype="double"
    )

    print("Camera Matrix :\n {0}".format(camera_matrix))

    dist_coeffs = np.zeros((5, 1))  # Assuming no lens distortion
    (success, rotation_vector, translation_vector) = cv2.solvePnP(model_points, image_points, camera_matrix,
                                                                  dist_coeffs, flags=cv2.SOLVEPNP_ITERATIVE)
    rotation_matrix = cv2.Rodrigues(rotation_vector)[0]
    print("Rotation Vector:\n {0}".format(rotation_vector))
    print('rotation_matrix:\n', rotation_matrix)
    print("Translation Vector:\n {0}".format(translation_vector))
    start_point = np.array([(0.0, 0.0, 1000.0)])

    one_nose_end_point2D = method_one(rotation_matrix, translation_vector, camera_matrix, dist_coeffs, start_point)

    two_nose_end_point2D = method_two(rotation_vector, translation_vector, camera_matrix, dist_coeffs, start_point)

    print('==one_nose_end_point2D:\n', one_nose_end_point2D)
    print('==two_nose_end_point2D:\n', two_nose_end_point2D)
    for p in image_points:
        cv2.circle(im, (int(p[0]), int(p[1])), 3, (0, 0, 255), -1)
    p1 = (int(image_points[0][0]), int(image_points[0][1]))
    p2 = (int(two_nose_end_point2D[0][0][0]), int(two_nose_end_point2D[0][0][1]))

    cv2.line(im, p1, p2, (255, 0, 0), 2)
if __name__ == '__main__':
    main()

c++:

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void method_two( vector<Point3d> &nose_end_point3D, vector<Point2d> &nose_end_point2D,
                 cv::Mat &rotation_vector, cv::Mat &translation_vector, cv::Mat &camera_matrix, cv::Mat &dist_coeffs){
    projectPoints(nose_end_point3D, rotation_vector, translation_vector, camera_matrix, dist_coeffs, nose_end_point2D);
}

void camera3d_to_img_2d(cv::Mat& x, cv::Mat &K, cv::Mat &Kd){
    x.rowRange(0, 2) = x.rowRange(0, 2) / x.row(2);

    cv::Mat r = x.row(0) * x.row(0) + x.row(1) * x.row(1);
    x.row(0) = x.row(0) * (1 + Kd.at<double>(0) * r + Kd.at<double>(1)*r*r + Kd.at<double>(4)*r*r*r) +
            2*Kd.at<double>(2)*x.row(0)*x.row(1) + Kd.at<double>(3)*(r + 2*x.row(0)*x.row(0));
    x.row(1) = x.row(1) * (1 + Kd.at<double>(0) * r + Kd.at<double>(1)*r*r + Kd.at<double>(4)*r*r*r) +
               2*Kd.at<double>(2)*x.row(0)*x.row(1) + Kd.at<double>(2)*(r + 2*x.row(1)*x.row(1));
    x.row(0) = K.at<double>(0, 0) * x.row(0) + K.at<double>(0, 1) * x.row(1) + K.at<double>(0, 2);
    x.row(1) = K.at<double>(1, 0) * x.row(0) + K.at<double>(1, 1) * x.row(1) + K.at<double>(1, 2);

}
void method_one( vector<Point3d> &nose_end_point3D, vector<Point2d> &nose_end_point2D,
                 cv::Mat &rotation_matrix, cv::Mat translation_vector, cv::Mat &camera_matrix, cv::Mat &dist_coeffs){
    cv::Mat start_point = cv::Mat(nose_end_point3D);
    start_point = start_point.reshape(1, 3);
    start_point.convertTo(start_point, rotation_matrix.type());
//    cout<<"start_point.rows:"<<start_point.rows<<endl;
//    cout<<start_point.cols<<endl;
//    cout<<rotation_matrix.rows<<endl;
//    cout<<"rotation_matrix.cols:"<<rotation_matrix.cols<<endl;
//    cout<<"start_point:"<<start_point<<endl;
//    cout<<"start_point.type():"<<start_point.type()<<endl;
    cv::Mat cam_3d = rotation_matrix*start_point + translation_vector;
//    cout<<cam_3d<<endl;
    camera3d_to_img_2d(cam_3d, camera_matrix, dist_coeffs);
    nose_end_point2D = cv::Mat_<Point2d>(cam_3d.rowRange(0, 2));
}
int main(int argc, char **argv)
{

    // Read input image
    cv::Mat im = cv::imread("/home/momenta/AI/c++_project_test/headPose.jpg");

    // 2D image points. If you change the image, you need to change vector
    std::vector<cv::Point2d> image_points;
    image_points.push_back( cv::Point2d(359, 391) );    // Nose tip
    image_points.push_back( cv::Point2d(399, 561) );    // Chin
    image_points.push_back( cv::Point2d(337, 297) );     // Left eye left corner
    image_points.push_back( cv::Point2d(513, 301) );    // Right eye right corner
    image_points.push_back( cv::Point2d(345, 465) );    // Left Mouth corner
    image_points.push_back( cv::Point2d(453, 469) );    // Right mouth corner

    // 3D model points.
    std::vector<cv::Point3d> model_points;
    model_points.push_back(cv::Point3d(0.0f, 0.0f, 0.0f));               // Nose tip
    model_points.push_back(cv::Point3d(0.0f, -330.0f, -65.0f));          // Chin
    model_points.push_back(cv::Point3d(-225.0f, 170.0f, -135.0f));       // Left eye left corner
    model_points.push_back(cv::Point3d(225.0f, 170.0f, -135.0f));        // Right eye right corner
    model_points.push_back(cv::Point3d(-150.0f, -150.0f, -125.0f));      // Left Mouth corner
    model_points.push_back(cv::Point3d(150.0f, -150.0f, -125.0f));       // Right mouth corner

    // Camera internals
    double focal_length = im.cols; // Approximate focal length.
    Point2d center = cv::Point2d(im.cols/2,im.rows/2);
    cv::Mat camera_matrix = (cv::Mat_<double>(3,3) << focal_length, 0, center.x,
            0 , focal_length, center.y,
            0, 0, 1);
    cv::Mat dist_coeffs = cv::Mat::zeros(5,1,cv::DataType<double>::type); // Assuming no lens distortion

    cout << "Camera Matrix " << endl << camera_matrix << endl ;
    // Output rotation and translation
    cv::Mat rotation_vector; // Rotation in axis-angle form
    cv::Mat translation_vector;

    // Solve for pose
    cv::solvePnP(model_points, image_points, camera_matrix, dist_coeffs, rotation_vector, translation_vector);

    cout<<"rotation_vector:"<<rotation_vector<<endl;
    cout<<"translation_vector:"<<translation_vector<<endl;
    cv::Mat rotation_matrix;
    cv::Rodrigues(rotation_vector,rotation_matrix);
    cout<<"rotation_matrix:"<<rotation_matrix<<endl;
    cout<<rotation_matrix.type()<<endl;
    // Project a 3D point (0, 0, 1000.0) onto the image plane.
    // We use this to draw a line sticking out of the nose
    vector<Point2d> one_nose_end_point2D;
    vector<Point3d> one_nose_end_point3D;
    one_nose_end_point3D.push_back(Point3d(0,0,1000.0));
    method_one(one_nose_end_point3D, one_nose_end_point2D,
                rotation_matrix, translation_vector, camera_matrix, dist_coeffs);
    cout<<"one_nose_end_point2D:"<<one_nose_end_point2D<<endl;

    vector<Point2d> two_nose_end_point2D;
    vector<Point3d> two_nose_end_point3D;
    two_nose_end_point3D.push_back(Point3d(0,0,1000.0));
    method_two(two_nose_end_point3D, two_nose_end_point2D, rotation_vector, translation_vector, camera_matrix, dist_coeffs);
    cout<<"two_nose_end_point2D:"<<two_nose_end_point2D<<endl;

    for(int i=0; i < image_points.size(); i++)
    {
        circle(im, image_points[i], 3, Scalar(0,0,255), -1);
    }

    cv::line(im,image_points[0], two_nose_end_point2D[0], cv::Scalar(255,0,0), 2);
    cv::imwrite("./im_show.jpg", im);

}

8.cv::floodFill 泛洪算法

python:

#!/usr/bin/env python

import cv2;
import numpy as np;

# Read image
im_in = cv2.imread("nickel.jpg", cv2.IMREAD_GRAYSCALE)

# Threshold.
# Set values equal to or above 220 to 0.
# Set values below 220 to 255.

th, im_th = cv2.threshold(im_in, 220, 255, cv2.THRESH_BINARY_INV)

# Copy the thresholded image.
im_floodfill = im_th.copy()

# Mask used to flood filling.
# Notice the size needs to be 2 pixels than the image.
h, w = im_th.shape[:2]
mask = np.zeros((h+2, w+2), np.uint8)

# Floodfill from point (0, 0)
cv2.floodFill(im_floodfill, mask, (0, 0), 255)

# Invert floodfilled image
im_floodfill_inv = cv2.bitwise_not(im_floodfill)

# Combine the two images to get the foreground.
im_out = im_th | im_floodfill_inv

# Display images.
cv2.imwrite("./Thresholded_Image.jpg", im_th)
cv2.imwrite("./Floodfilled_Image.jpg", im_floodfill)
cv2.imwrite("./Inverted_Floodfilled_Image.jpg", im_floodfill_inv)
cv2.imwrite("./Foreground.jpg", im_out)

c++:

#include "opencv2/opencv.hpp"

//using namespace cv;

int main(int argc, char **argv)
{
    // Read image
    cv::Mat im_in = cv::imread("./nickel.jpg", cv::IMREAD_GRAYSCALE);

    // Threshold.
    // Set values equal to or above 220 to 0.
    // Set values below 220 to 255.
    cv::Mat im_th;
    cv::threshold(im_in, im_th, 220, 255, cv::THRESH_BINARY_INV);

    // Floodfill from point (0, 0)
    cv::Mat im_floodfill = im_th.clone();
    cv::floodFill(im_floodfill, cv::Point(0,0), cv::Scalar(255));

    // Invert floodfilled image
    cv::Mat im_floodfill_inv;
    cv::bitwise_not(im_floodfill, im_floodfill_inv);

    // Combine the two images to get the foreground.
    cv::Mat im_out = (im_th | im_floodfill_inv);

    // Display images
    cv::imwrite("Thresholded_Image.jpg", im_th);
    cv::imwrite("Floodfilled_Image.jpg", im_floodfill);
    cv::imwrite("Inverted_Floodfilled_Image.jpg", im_floodfill_inv);
    cv::imwrite("Foreground.jpg", im_out);

}

 

9.cv::findHomography

传两个图像里的点集合,它会找到那个目标的透视转换,需要至少4个正确的点来找变换。

python:

#!/usr/bin/env python

import cv2
import numpy as np


def mouse_handler(event, x, y, flags, data):
    if event == cv2.EVENT_LBUTTONDOWN:
        cv2.circle(data['im'], (x, y), 3, (0, 0, 255), 5, 16);
        cv2.imshow("Image", data['im']);
        if len(data['points']) < 4:
            data['points'].append([x, y])

def get_four_points(im):
    # Set up data to send to mouse handler
    data = {}
    data['im'] = im.copy()
    data['points'] = []

    # Set the callback function for any mouse event
    cv2.imshow("Image", im)
    cv2.setMouseCallback("Image", mouse_handler, data)
    cv2.waitKey(0)

    # Convert array to np.array
    points = np.vstack(data['points']).astype(float)

    return points


if __name__ == '__main__' :

    # Read in the image.
    im_src = cv2.imread("book1.jpg")

    # Destination image
    size = (300, 400, 3)

    im_dst = np.zeros(size, np.uint8)
    
    pts_dst = np.array(
                       [
                        [0, 0],
                        [size[0] - 1, 0],
                        [size[0] - 1, size[1] -1],
                        [0, size[1] - 1]
                        ], dtype=float
                       )
    

    # Show image and wait for 4 clicks.
    # cv2.imshow("Image", im_src)
    pts_src = get_four_points(im_src)
    print('==pts_src:', pts_src)
    # Calculate the homography
    matrix, status = cv2.findHomography(pts_src, pts_dst)
    print('==matrix:', matrix)
    # Warp source image to destination
    im_dst = cv2.warpPerspective(im_src, matrix, size[0:2])
    print('==im_dst.shape:', im_dst.shape)
    # Show output
    cv2.imshow("Image", im_dst)
    cv2.waitKey(0)


c++:

#include <opencv2/opencv.hpp>

//using namespace cv;
using namespace std;

struct userdata{
    cv::Mat im;
    vector<cv::Point2f> points;
};

void mouseHandler(int event, int x, int y, int flags, void* data_ptr)
{
    if  ( event == cv::EVENT_LBUTTONDOWN )
    {
        userdata *data = ((userdata *) data_ptr);
        cv::circle(data->im, cv::Point(x,y),3,cv::Scalar(0,0,255), 5, cv::LINE_AA);
        imshow("Image", data->im);
        if (data->points.size() < 4)
        {
            data->points.push_back(cv::Point2f(x,y));
        }
    }
}

int main( int argc, char** argv)
{

    // Read source image.
    cv::Mat im_src = cv::imread("/home/fzh/AI/C_learn/datastruct/opencv/book1.jpg");

    // Destination image. The aspect ratio of the book is 3/4
    cv::Size size(300,400);
    cv::Mat im_dst = cv::Mat::zeros(size,CV_8UC3);

    // Create a vector of destination points.
    vector<cv::Point2f> pts_dst;

    pts_dst.push_back(cv::Point2f(0,0));
    pts_dst.push_back(cv::Point2f(size.width - 1, 0));
    pts_dst.push_back(cv::Point2f(size.width - 1, size.height -1));
    pts_dst.push_back(cv::Point2f(0, size.height - 1 ));

    // Set data for mouse event
    cv::Mat im_temp = im_src.clone();
    userdata data;
    data.im = im_temp;

    cout << "Click on the four corners of the book -- top left first and" << endl
         << "bottom left last -- and then hit ENTER" << endl;

    // Show image and wait for 4 clicks.
    imshow("Image", im_temp);
    // Set the callback function for any mouse event
    cv::setMouseCallback("Image", mouseHandler, &data);
    cout<<"data.im.rows:"<<data.im.rows<<endl;
    cout<<"data.im.cols:"<<data.im.cols<<endl;
    cout<<"data.im.channels():"<<data.im.channels()<<endl;

    cv::waitKey(0);

    // Calculate the homography
    cv::Mat matrix = cv::findHomography(data.points, pts_dst);
    cout<<"data.points:"<<data.points<<endl;
    // Warp source image to destination
    cv::warpPerspective(im_src, im_dst, matrix, size);

    // Show image
    cv::imshow("Image", im_dst);
    cv::waitKey(0);
    cv::imwrite("./dst.jpg",im_dst);
    return 0;
}

//

 

10. cv2::moments 寻找质心

python:

import cv2
import numpy as np
import argparse

# # create object to pass argument
# arg_parse = argparse.ArgumentParser()
# arg_parse.add_argument("-i", "--ipimage", required=True,
# 	help="input image path")
# args = vars(arg_parse.parse_args())
img_path = './circle.png'
# read image through command line 
img = cv2.imread(img_path)

# convert image to grayscale image
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 
# convert the grayscale image to binary image
ret, thresh = cv2.threshold(gray_image, 127, 255, 0)

cv2.imwrite('./thresh.jpg', thresh)
# calculate moments of binary image
M = cv2.moments(thresh)
print('==M:', M)
print('==M.keys()', M.keys())
# calculate x,y coordinate of center
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
 
# put text and highlight the center
cv2.circle(img, (cX, cY), 5, (255, 255, 255), -1)
cv2.putText(img, "centroid", (cX - 25, cY - 25), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
cv2.imwrite('./img_show.jpg', img)

c++:

//#include "opencv2/highgui/highgui.hpp"
//#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    // Declare Mat type images
    Mat src, gray,thr;
    string img_path="/home/momenta/AI/c++_project_test/circle.png";
    //Load source image, convert it to gray
    src = imread(img_path, 1 );

    // convert image to grayscale
    cvtColor(src, gray, COLOR_BGR2GRAY );

    // convert grayscale to binary image
    threshold( gray, thr, 100,255,THRESH_BINARY );

    // find moments of the image
    Moments m = moments(thr,true);
    cv::Point2i p(m.m10/m.m00, m.m01/m.m00);

    // coordinates of centroid

    cout<< "Mat(p):"<< Mat(p)<< endl;
    cout<< "p:"<< p<< endl;
    // show the image with a point mark at the centroid
    circle(src, p, 5, Scalar(128,0,0), -1);
    p.x -= 25;
    p.y -= 25;
    cv::putText(src, "centroid", p, cv::FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255), 2);
    imwrite("./img_show.jpg",src);
//    imshow("Image with center",src);
//    waitKey(0);
}

多个图案的;

python:

import cv2
import numpy as np
import argparse

# create object to pass argument
# arg_parse = argparse.ArgumentParser()
# arg_parse.add_argument("-i", "--ipimage", required=True,
# 	help="input image path")
# args = vars(arg_parse.parse_args())
img_path = './multiple-blob.png'
# read image through command line 
img = cv2.imread(img_path)
# convert the image to grayscale
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# convert the grayscale image to binary image
ret, thresh = cv2.threshold(gray_image, 127, 255, 0)
cv2.imwrite('./thresh.jpg', thresh)
# find contour in the binary image
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print(hierarchy.shape)
print(hierarchy)
# [-1, -1, 1, -1;
#  2, -1, -1, 0;
#  3, 1, -1, 0;
#  4, 2, -1, 0;
#  5, 3, -1, 0;
#  7, 4, 6, 0;
#  -1, -1, -1, 5;
#  -1, 5, -1, 0]
print(len(contours))
for c in contours[1:]:
	# calculate moments for each contour
	M = cv2.moments(c)
	cX = int(M["m10"] / M["m00"])
	cY = int(M["m01"] / M["m00"])

	# calculate x,y coordinate of center
	cv2.circle(img, (cX, cY), 5, (0, 0, 0), -1)
	cv2.putText(img, "centroid", (cX - 25, cY - 25), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2)
# 	# display the imagecv2.findContours
	cv2.imshow("Image", img)
	cv2.waitKey(0)


c++:

//#include "opencv2/highgui/highgui.hpp"
//#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

RNG rng(12345);

void find_moments( Mat src );

int main(int argc, char** argv)
{
    string img_path="/home/momenta/AI/c++_project_test/multiple-blob.png";
    /// Load source image, convert it to gray
    Mat src, gray;
    src = imread(img_path, 1 );

    cvtColor( src, gray, COLOR_BGR2GRAY );

    Mat thresh;
    vector<vector<Point2i> > contours;
    vector<Vec4i> hierarchy;

    /// Detect edges using canny
//    Canny( gray, canny_output, 50, 150, 3 );
    // Find contours
    threshold(gray, thresh, 127,255,THRESH_BINARY );
    findContours( thresh, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
    cout<<Mat(hierarchy)<<endl;
    cout<<Mat(hierarchy).size<<endl;
    /// Get the moments
    vector<Moments> mu(contours.size());
    for( int i = 0; i < contours.size(); i++ )
    { mu[i] = moments( contours[i], false ); }

    ///  Get the centroid of figures.
    vector<Point2f> mc(contours.size());
    for( int i = 0; i < contours.size(); i++ )
    {
        mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00);
    }

    /// Draw contours
    for( int i = 0; i< contours.size(); i++ )
    {
        Scalar color = Scalar(0,0,0);
//        drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
        circle(src, mc[i], 4, color, -1, 7, 0 );
        mc[i].x -=25;
        mc[i].y -=25;
        cv::putText(src, "centroid", mc[i], cv::FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0), 2);
    }
    /// Show the resultant image
    imwrite("./img_show.jpg", src);

    return(0);
}

 

11.cv2::applyColorMap与cv::Rect切ROI

python:

import cv2
import numpy as np


def colormap_name(id):
    switcher = {
        0: "COLORMAP_AUTUMN",
        1: "COLORMAP_BONE",
        2: "COLORMAP_JET",
        3: "COLORMAP_WINTER",
        4: "COLORMAP_RAINBOW",
        5: "COLORMAP_OCEAN",
        6: "COLORMAP_SUMMER",
        7: "COLORMAP_SPRING",
        8: "COLORMAP_COOL",
        9: "COLORMAP_HSV",
        10: "COLORMAP_PINK",
        11: "COLORMAP_HOT"
        
    }
    return switcher.get(id, "NONE")


if __name__ == '__main__':

    im = cv2.imread("./pluto.jpg", cv2.IMREAD_GRAYSCALE)
    im_out = np.zeros((600, 800, 3), np.uint8)

    for i in range(0, 4):
        for j in range(0, 3):
            k = i + j * 4
            im_color = cv2.applyColorMap(im, k)
            cv2.putText(im_color, colormap_name(k), (30, 180), cv2.FONT_HERSHEY_DUPLEX, 0.5, (255, 255, 255), 1)
            
            im_out[j*200: j*200 + 200, i*200: i*200 + 200, :] = im_color

    cv2.imwrite('./im_out.jpg', im_out)

c++:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

string colormap_name(int id)
{
    switch(id){
        case COLORMAP_AUTUMN :
            return "COLORMAP_AUTUMN";
        case COLORMAP_BONE :
            return "COLORMAP_BONE";
        case COLORMAP_JET :
            return "COLORMAP_JET";
        case COLORMAP_WINTER :
            return "COLORMAP_WINTER";
        case COLORMAP_RAINBOW :
            return "COLORMAP_RAINBOW";
        case COLORMAP_OCEAN :
            return "COLORMAP_OCEAN";
        case COLORMAP_SUMMER:
            return "COLORMAP_SUMMER";
        case COLORMAP_SPRING :
            return "COLORMAP_SPRING";
        case COLORMAP_COOL :
            return "COLORMAP_COOL";
        case COLORMAP_HSV :
            return "COLORMAP_HSV";
        case COLORMAP_PINK :
            return "COLORMAP_PINK";
        case COLORMAP_HOT :
            return "COLORMAP_HOT";
    }

    return "NONE";
}

int main(){
    // Read 8-bit grayscale image
    Mat im = imread("pluto.jpg", IMREAD_GRAYSCALE);
    cout<<im.cols<<endl;
    cout<<im.rows<<endl;
    Mat im_out = Mat::zeros(600, 800, CV_8UC3);

    for (int i=0; i < 4; i++){
        for(int j=0; j < 3; j++){
            int k = i + j * 4;
            Rect temp_region = Rect(i * 200, j * 200, 200, 200);
            cout<<"temp_region lx:"<<temp_region.x<<endl;
            cout<<"temp_region ly:"<<temp_region.y<<endl;
            Mat im_color = im_out(temp_region);
            applyColorMap(im, im_color, k);
            putText(im_color, colormap_name(k), Point(30, 180), cv::FONT_HERSHEY_DUPLEX, 0.5, Scalar::all(255), 1, cv::LINE_AA);
        }
    }
    imwrite("./im_out.jpg", im_out);
    return 0;
};

 

12.cv::convexHull 与cv::drawContours

python:

import cv2
import numpy as np
import sys

if __name__ == "__main__":
    if(len(sys.argv)) < 2:
        file_path = "sample.jpg"
    else:
        file_path = sys.argv[1]

    # read image
    src = cv2.imread(file_path, 1)
    
    # show source image
    cv2.imshow("Source", src)

    # convert image to gray scale
    gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
     
    # blur the image
    blur = cv2.blur(gray, (3, 3))
    
    # binary thresholding of the image
    ret, thresh = cv2.threshold(blur, 200, 255, cv2.THRESH_BINARY)
    
    # find contours
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, \
            cv2.CHAIN_APPROX_SIMPLE)
    
    # create hull array for convexHull points
    hull = []
    
    # calculate points for each contour
    for i in range(len(contours)):
        hull.append(cv2.convexHull(contours[i], False))
    
    # create an empty black image
    drawing = np.zeros((thresh.shape[0], thresh.shape[1], 3), np.uint8)
    
    # draw contours and hull points
    for i in range(len(contours)):
        color_contours = (0, 255, 0) # color for contours
        color = (255, 255, 255) # color for convex hull
        # draw contours
        cv2.drawContours(drawing, contours, i, color_contours, 2, 8, hierarchy)
        # draw convex hull
        cv2.drawContours(drawing, hull, i, color, 2, 8)

    cv2.imshow("Output", drawing)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

c++:

//#include "opencv2/highgui/highgui.hpp"
//#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdlib>

using namespace cv;
using namespace std;

int main(int argc, char** argv) {
    string image_path; // image path for input image

    if(argc < 2)
        image_path = "sample.jpg";
    else
        image_path = argv[1];

    // declare images
    Mat src, gray, blur_image, threshold_output;

    // take input image
    src = imread(image_path, 1);
    cout<<"src.rows:"<<src.rows<<endl;
    cout<<"src.cols:"<<src.cols<<endl;
    cout<<"src.channels():"<<src.channels()<<endl;
    // convert to grayscale
    cvtColor(src, gray, COLOR_BGR2GRAY);

    // add blurring to the input image
    blur(gray, blur_image, Size(3, 3));

    // binary threshold the input image
    threshold(gray, threshold_output, 200, 255, THRESH_BINARY);

    // show source image
//    namedWindow("Source", WINDOW_AUTOSIZE);
//    imshow("Source", src);

    // Convex Hull implementations
    Mat src_copy = src.clone();

    // contours vector
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;

    // find contours for the thresholded image
    findContours(threshold_output, contours, hierarchy, RETR_TREE,
                 CHAIN_APPROX_SIMPLE, Point(0, 0));

    // create convex hull vector
    vector<vector<Point2i>> hull(contours.size());

    // find convex hull for each contour
    for(int i = 0; i < contours.size(); i++){
        convexHull(Mat(contours[i]), hull[i], false);
//        cout<<"hull[i]:"<<hull[i].size()<<endl;
    }
    // create empty black image
    Mat drawing = Mat::zeros(threshold_output.size(), CV_8UC3);

    // draw contours and convex hull on the empty black image
    for(int i = 0; i < contours.size(); i++) {
        Scalar color_contours = Scalar(0, 255, 0); // color for contours : green
        Scalar color = Scalar(255, 255, 255); // color for convex hull : white
        // draw contours
        drawContours(drawing, contours, i, color_contours, 2, 8, vector<Vec4i>(), 0, Point());
        // draw convex hull
        drawContours(drawing, hull, i, color, 2, 8, vector<Vec4i>(), 0, Point());
    }
    imwrite("./drawing.jpg",drawing);
//    namedWindow("Output", WINDOW_AUTOSIZE);
//    imshow("Output", drawing);
//
//    waitKey(0);
    return 0;
}

  

13.cv::Point系列与修改像素值

可以看见没有unsigned char

可以自己写一个

typedef cv::Point3_<uint8_t> Pixel;

注意的是unsigned char 打印的是ascii玛,需要转一下才能打印值,可以通过上诉形式,取像素值进行修改.

方法1:通过for循环修改像素值


void complicatedThreshold(Pixel &pixel)
{
//  if (pow(double(pixel.x)/10,2.5) > 100)
    if (double(pixel.x)/10 > 10)
    {
        pixel.x = 255;
        pixel.y = 255;
        pixel.z = 255;
    }
    else
    {
        pixel.x = 0;
        pixel.y = 0;
        pixel.z = 0;
    }
}

    for (int i = 0; i < image.rows; i++)
        {
            // Loop over all columns
            for ( int j = 0; j < image.cols; j++)
            {
                Pixel pixel = image.at<Pixel>(i,j);
                cout<<"int(pixel.x)"<<int(pixel.x)<<int(pixel.y)<<int(pixel.z)<<endl;
            // Apply complicatedTreshold
                complicatedThreshold(pixel);
            // Put result back
                image.at<cv::Vec3b>(i,j) = pixel;
            }
        }
cv::imwrite("image.jpg", image);

方法2:指针

        cv::Mat image1 = image.clone();
        Pixel* pixel = image1.ptr<Pixel>(0,0);
        // Mat objects created using the create method are stored
//        // in one continous memory block.
        const Pixel* endPixel = pixel + image1.cols * image1.rows;
//
//        // Loop over all pixels
        for (; pixel != endPixel; pixel++)
        {
            complicatedThreshold(*pixel);
        }
        cv::imwrite("image1_th.jpg", image1);

  

14.cv::Range切片

    cv::Mat probMap = (cv::Mat_<float>(3, 3) <<0,10,0,1,2,3,4,5,6);
    cv::Point maxLoc;
    double prob;
    cout<<"probMap:"<<probMap<<endl;
    cv::minMaxLoc(probMap, 0, &prob, 0, &maxLoc);
    cout<<"maxLoc.x:"<<maxLoc.x<<endl;
    cout<<"maxLoc.y"<<maxLoc.y<<endl;

    cv::Mat roi = probMap(cv::Range(0, 2), cv::Range(0, 1));
    cout<<"==roi:"<<roi<<endl;
    cout<<"==roi.size:"<<roi.size<<endl;

15.合成图片

    // 构建新图像的大小
    int width = src1.cols + src2.cols;
    int height = max(src1.rows, src2.rows);
    cv::Mat two = cv::Mat::zeros(cv::Size(width, height), src1.type());
    // 构建ROI
    cv::Rect r1(0, 0, src1.cols, src1.rows);
    cv::Rect r2(0, 0, src2.cols, src2.rows);
    cout<<"==r2.x:"<<r2.x<<endl;
    cout<<"==r2.y:"<<r2.y<<endl;
    cout<<"==r2.height:"<<r2.height<<endl;
    cout<<"==r2.width:"<<r2.width<<endl;
    r2.x = src1.cols;
    r2.y = 0;
    // 内容copy
    src1.copyTo(two(r1));
    src2.copyTo(two(r2));
    cout<<"==two.rows:"<<two.rows<<endl;
    cout<<"==two.cols:"<<two.cols<<endl;
    cv::imwrite("./merge.jpg", two);

16.遍历文件夹图片cv::glob

    std::vector<cv::String> imgs_list_path;
    // Path of the folder containing checkerboard images
    std::string img_dir_path = "../imgs/*";

    cv::glob(img_dir_path, imgs_list_path);
    
    for(size_t i=0; i < imgs_list_path.size(); i++){
        cout<<"imgs_list_path[i]:"<<imgs_list_path[i]<<endl;
    }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ opencv的一些基础知识 的相关文章

  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • 根据属性的类型使用文本框或复选框

    如果我有这样的结构 public class Parent public string Name get set public List
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • DotNetZip:如何提取文件,但忽略zip文件中的路径?

    尝试将文件提取到给定文件夹 忽略 zip 文件中的路径 但似乎没有办法 考虑到其中实现的所有其他好东西 这似乎是一个相当基本的要求 我缺少什么 代码是 using Ionic Zip ZipFile zf Ionic Zip ZipFile
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么

随机推荐

  • 用python画二元函数图像

    利用Python的Matplotlib库可以实现二元函数的可视化 以下以一段代码说明 第三方库需求 Matplotlib 数据可视化 numpy 数学计算库 代码 import matplotlib pyplot as plt import
  • 控制反转 的种类

    之前对控制反转的定义和解释都不是很清晰 最近翻书发现在 Pro Spring 5 免费电子版在文章最后 有一段非常不错的解释 记录一下 有道翻译贴出来方便查看 如有请直接跳过中文 看后面的原文 控制反转的类型 控制反转的类型您可能想知道为什
  • CMake:消灭error(一)

    使用CMake 遇到的第一个错误 CMake Error CMake can not determine linker language for target hello CMake Error Cannot determine link
  • 微信小程序 首页弹出用户协议

    话不多说 直接上代码 wxml
  • 经典神经网络总结

    1 LeNet 5 3层卷积 2层全连接 第一个CNN网络 由 L e C u n LeCun LeCun提出 用于手写数字识别 1 1 网络结构 1 2 各层参数详解 0 INPUT层 输入层 输入图像
  • Python 自动发送邮件实战案例,人人都可以学会

    自动发送邮件能应用于许多场景 比如我想要知道股票策略中的股票池是否有实时的更新 这时候如果再拉一遍数据 跑一遍脚本 实在是太浪费时间了 为什么不把这一套流程放到服务器上 然后到点自动运行并发送邮件呢 类似的应用场景还有很多 不仅仅是在股票策
  • Android系统启动流程

    Android系统启动流程学习 会对Android系统与Linux系统的关系有一个更深的理解 Android启动流程 Android启动时序图 Linux启动 开机过电 复位器件 执行Bootloader程序 arm中是uboot或者fas
  • 经历一些事,认清一些人

    你发现了吗 随着年龄的增长 我们身边的朋友没有变多 反而越来越少了 这是我们的交友能力逐渐在下滑吗 其实不然 这是因为随着经历的事情多了 我们具备了认清别人的能力 能够分辨哪些是生命中的过客 哪些是值得珍惜的挚友 1 高分美剧 后翼弃兵 中
  • 3D游戏设计——AR/MR技术

    HW12 AR小游戏设计 本次AR小游戏并没有给出什么要求 由于大作业实在太多了 所以这篇博客重点在于怎么配置环境 并实现图片识别的功能 虚拟按键的玩法暂时没有想到什么好的点子 会在之后比较有空时详细设计 并补充完整 求TA手下留情 配置环
  • Bootstrap4 模态对话框示例

  • Java中"abc" instanceof Object返回结果

    返回结果 true instanceof 是Java的一个二元操作符 和 gt lt 是同一类的比较运算符 因为它由字母组成的 所以也是Java的关键保留字 它的作用是测试它左边的对象是否是它右边类的实例 返回boolean类型数据 abc
  • Android如何离线播放加密(HLS)m3u8视频——实现HLS缓存

    HTTP Live Streaming HLS 是苹果公司 Apple Inc 实现的基于HTTP的流媒体传输协议 可实现流媒体的直播和点播 主要应用在iOS系统 为iOS设备 如iPhone iPad 提供音视频直播和点播方案 它的工作原
  • MES制造执行系统的原理与实现

    前言 近些年来 我国已经涌现了大量的制造型企业 随着竞争的发展 对产品质量的要求越来越高 特别是在电子制造型的企业里 对于制造流程控制的要求不断提升 许多企业为了增强竞争力 不惜重金实施ERP 系统 以求缩减成本控制 缩短供货周期 但在内部
  • 微信小程序——操作数组

    1 数组 排序 过滤 求和 去重 乱序 let array sort 数组正序 array 5 4 3 2 1 console log array sort reverse 数组倒序 array 1 2 3 4 5 console log
  • 人工智能谓词逻辑——猴子摘香蕉问题

    案例 我们要实现以下步骤 让猴子得到香蕉 但是直接跳够不到 必须站在箱子上才能取到 这个案例共有以下几种情况 猴子香蕉箱子在同一处 猴子香蕉在同一处 香蕉箱子在同一出 还有三者均不在同一处 但不论是哪种情况 我们需要清楚一点就算是香蕉和猴子
  • CUDA Samples: image normalize(mean/standard deviation)

    以下CUDA sample是分别用C 和CUDA实现的通过均值和标准差对图像进行类似归一化的操作 并对其中使用到的CUDA函数进行了解说 各个文件内容如下 关于均值和标准差的计算公式可参考 http blog csdn net fengbi
  • 【Kettle从零开始】第八弹之Kettle变量参数传递介绍

    对于ETL参数传递是一个很重要的环节 因为参数的传递会涉及到业务数据是如何抽取 下面我为大家举例一个简单的需求 需求说明 需要抽取昨天的数据装载到目标表中 1 参数作用域 答 Kettle中参数大致可分为两类 一类是全局参数 一类是局部参数
  • Linus系统的详细安装教程:

    第一步 首先创建虚拟机 1 打开VMware 点击左上角新建虚拟机如下 2 选择相关选项 也可以选自定义 自定义完成下一步即可 如下图 3 选择 稍后安装操作系统 S 如下图 4 版本也可以选择其他的Red Hat版本 CentOS是Red
  • 003 冒泡排序法的详细实现过程——“C”

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 冒泡排序法是什么 二 实现过程 1 图解 一次的冒泡排序 一 冒泡排序法是什么 冒泡排序是一种交换排列 基本思想是比较前后的关键字 如果反序则交换 直到有
  • C++ opencv的一些基础知识

    一 基础知识 1 cv mat type返回数字对应的类型 C1 C2 C3 C4 指的是通道 Channel 数 比如3通道的float 32 cv Mat M5 cv Mat zeros 2 3 CV 32FC 3 2 at方法数据类型