OpenCV笔记

Linux上Opencv的安装

如果没有安装 OpenCV:
    从 https://opencv.org/releases/ 下载opencv-3.4.16.zip

    sudo apt update
    sudo apt install -y cmake g++ wget unzip cmake build-essential \
                        libgtk2.0-dev libavcodec-dev libavformat-dev libswscale-dev libtbb2 \
                        libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev

    sudo mkdir -p /opt/tools
    cd opencv-3.4.16
    mkdir release && cd release
    cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/opt/tools/opencv-3.4.16 ..
    make -j8
    sudo make install

    参考了:https://docs.opencv.org/master/d7/d9f/tutorial_linux_install.html

使用opencv读取、显示和写入图像

C++和Python代码

C++

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

int main()
{
    // 读取图像
    Mat img_grayscale = imread("../1.jpg",0);
    // 显示图像
    imshow("grayscale image", img_grayscale);
    // 监听键盘,0为无限期等待击键
    waitKey(0);
    // 销毁创建的所有窗口
    destroyAllWindows();
    // 写入图片
    imwrite("grayscale.jpg",img_grayscale);
    return 0;
}

Python

# import the cv2 library
import cv2

# The function cv2.imread() is used to read an image.
img_grayscale = cv2.imread('test.jpg',0)

# The function cv2.imshow() is used to display an image in a window.
cv2.imshow('graycsale image',img_grayscale)

# waitKey() waits for a key press to close the window and 0 specifies indefinite loop
cv2.waitKey(0)

# cv2.destroyAllWindows() simply destroys all the windows we created.
cv2.destroyAllWindows()

# The function cv2.imwrite() is used to write an image.
cv2.imwrite('grayscale.jpg',img_grayscale)
1.imread() 读取图片
  • 语法imread(filename, flags)

    第一个参数: 图像名
    第二个参数:[optional flag]
    	cv2.IMREAD_UNCHANGED  or -1
    	cv2.IMREAD_GRAYSCALE  or 0
    	cv2.IMREAD_COLOR  or 1  # 这个是默认值,读取图片作为彩色图片
    
  • 注意

    OpenCV读取出来的是BGR格式,但是其他cv库使用的是RGB格式(所以有时候需要转换格式)
    例如:
    from matplotlib import pyplot as plt
    plt.axis("off")
    plt.imshow(cv2.cvtColor(img_color, cv2.COLOR_BGR2RGB))
    plt.show()
    
2.imshow() 在窗口展示图片
  • imshow(window_name, image)

    第一个参数是窗口名
    第二个是需要展示的图片
    
    要一次显示多个图像,请为要显示的每个图像指定一个新窗口名称。
    该函数一般和waitKey(),destroyAllWindows() / destroyWindow()一起使用
    waitKey()是键盘响应函数,它需要一个参数: 显示窗口的时间(单位毫秒),如果是0则无限期等待击键。
    还可以设置该功能以检测键盘上的 Q 键或 ESC 键等特定击键,从而更明确地告诉哪个键应该触发哪个行为
    
  • 案例

    python

    #Displays image inside a window
    cv2.imshow('color image',img_color)  
    cv2.imshow('grayscale image',img_grayscale)
    cv2.imshow('unchanged image',img_unchanged)
    
    # Waits for a keystroke
    cv2.waitKey(0)  # 0表示一直等待,也可以填具体时间单位是毫秒。可以通过返回值来判断是q or ESC
    
    # Destroys all the windows created
    cv2.destroyAllwindows() 
    

    c++

    // Create a window.
    namedWindow( "color image", WINDOW_AUTOSIZE );
    namedWindow( "grayscale image", WINDOW_AUTOSIZE );
    namedWindow( "unchanged image", WINDOW_AUTOSIZE );
    
    // Show the image inside it.
    imshow( "color image", img_color ); 
    imshow( "grayscale image", img_grayscale );
    imshow( "unchanged image", img_unchanged ); 
    
    // Wait for a keystroke.   
    waitKey(0);  
    
    // Destroys all the windows created                         
    destroyAllWindows();
    
3.imwrite() 写文件到文件目录
  • imwrite(filename, image)

    第一个参数是文件名,必须包括文件扩展名(.png, .jpg etc)
    第二个参数是保存的图片,如果保存成功返回True
    
  • 案例

    python

    cv2.imwrite('grayscale.jpg',img_grayscale)
    

    c++

    imwrite("grayscale.jpg", img_grayscale);
    

使用opencv读写视频

C++和Python读写视频代码

C++

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


int main()
{
    //cv2.VideoCapture– 创建一个视频捕获对象,这将有助于流式传输或显示视频。
    //cv2.VideoWriter– 将输出视频保存到目录中。
    //创建一个VideoCapture对象,然后我们将使用它来读取视频文件。
    //将vid_capture("../1.mp4")变成vid_capture(0)则是获取摄像头
    VideoCapture vid_capture("../1.mp4");

    //判断是否正确打开视频文件
    if(!vid_capture.isOpened())
    {
        cout<<"Error opening video stream or file"<<endl;
    }    
    else
    {   
        //get函数记录的选项枚举列表中获取单个参数。
        //数值 5 和 7,它们对应于帧速率 (CAP_PROP_FPS) 和帧数 ( CAP_PROP_FRAME_COUNT)。可以提供数值或名称。
        int fps = vid_capture.get(5);
        cout<<"FPS: "<<fps<<endl;

        //获取视频的总帧数
        int frame_count = vid_capture.get(7);
        cout<<"Frame count: "<<frame_count<<endl;
    }

    while(vid_capture.isOpened())
    {
        //Mat是一个图像类容器,n维数组
        Mat frame;
        //vid_capture.read()通过使用该方法创建循环并一次从视频流中读取一帧
        bool  isSuccess = vid_capture.read(frame);

        if(isSuccess == true)
        {
            //显示当前帧
            imshow("Video", frame);
        }
        
        if(isSuccess == false)
        {
            cout<<"Video camera is disconnected"<<endl;
            break;
        }

        if(waitKey(20) == 'q')
        {
            cout<<"q key is pressed by the user. Stopping the video"<<endl;
            break;
        }
    }
    //释放视频资源
    vid_capture.release();
    //关闭窗口
    destroyAllWindows();
    return 0;
}

Python

import cv2 

# Create a video capture object, in this case we are reading the video from a file
vid_capture = cv2.VideoCapture('Resources/Cars.mp4')  # 创建一个视频捕捉对象,有助于流式传输或显示视频

if (vid_capture.isOpened() == False):  # isOpened()方法判断视频文件是否打开正确
	print("Error opening the video file")
# Read fps and frame count
else:
	# Get frame rate information
	# You can replace 5 with CAP_PROP_FPS as well, they are enumerations
	fps = vid_capture.get(5)  # get() 方法得到视频流的元数据,注意该方法不适合web cameras.# 5代表frame rate(帧率fps)
	print('Frames per second : ', fps,'FPS')

	# Get frame count
	# You can replace 7 with CAP_PROP_FRAME_COUNT as well, they are enumerations
	frame_count = vid_capture.get(7)  # 7代表帧数(frame count)
	print('Frame count : ', frame_count)

while(vid_capture.isOpened()):
	# vid_capture.read() methods returns a tuple, first element is a bool 
	# and the second is frame
    # 一帧一帧的读取
	ret, frame = vid_capture.read()  # read()放回元组,第一个是boolean[True表示视频流包含要读取的帧], 第二个是实际的视频帧
	if ret == True:
		cv2.imshow('Frame',frame)
		# 20 is in milliseconds, try to increase the value, say 50 and observe
		key = cv2.waitKey(20)
		
		if key == ord('q'):
			break
	else:
		break

# Release the video capture object
vid_capture.release()  # 释放视频捕捉对象
cv2.destroyAllWindows()  # 关闭所有窗口
1.读图片序列

python

vid_capture = cv2.VideoCapture('Resources/Image_sequence/Cars%04d.jpg')

c++

VideoCapture vid_capture("Resources/Image_sequence/Cars_%04d.jpg");
//%d左对齐,输出变量的所有数字;%4d右对齐,宽度为4,左边填充空格,当变量的实际宽度大于4时,输出变量的所有数字;%04d与%4d的唯一区别就是左边填充0。
//以%d,%4d,%04d,输出12时, 结果是:12,两个空格12, 0012。
//注意: 该数据的形式是: (Cars_01.jpg, Cars_02.jpg, Cars_03.jpg, etc…)
2.VideoWriter()写入视频

Python

import cv2

vid_capture = cv2.VideoCapture("video/test.mp4")

frame_width = int(vid_capture.get(3))
frame_height = int(vid_capture.get(4))
frame_size = (frame_width, frame_height)

output = cv2.VideoWriter("video/out_video.avi",
                         cv2.VideoWriter_fourcc('M','J','P','G'),
                         20,
                         frame_size
                         )
while(vid_capture.isOpened()):
    ret, frame = vid_capture.read()
    if ret == True:
        output.write(frame)
    else:
        print("Stream disconnected")
        break

vid_capture.release()
output.release()
  • 前置知识: 获取视频帧的width和height

Python

# Obtain frame size information using get() method
frame_width = int(vid_capture.get(3))
frame_height = int(vid_capture.get(4))
frame_size = (frame_width,frame_height)
fps = 20

c++

// Obtain frame size information using get() method
Int frame_width = static_cast<int>(vid_capture.get(3));
int frame_height = static_cast<int>(vid_capture.get(4));
Size frame_size(frame_width, frame_height);
int fps = 20;
  • 语法: VideoWriter(filename, apiPreference, fourcc, fps, frameSize[, isColor])

    filename: 输出文件的路径
    apiPreference: API后端标识符
    fourcc: 编解码器的 4 字符代码,用于压缩帧
    fps: 创建的视频流的帧率
    fram_size: 视频帧的大小
    isCOlor: 如果不为零,编码器将期望并编码彩色帧。 否则它将适用于灰度帧(该标志目前仅在 Windows 上受支持)
    
  • 一个特殊的便利函数用于检索四字符编解码器,需要作为视频写入器对象 cv2 的第二个参数

    • VideoWriter_fourcc('M', 'J', 'P', 'G') in Python.
    • VideoWriter::fourcc('M', 'J', 'P', 'G') in C++.
  • 视频编解码器指定如何压缩视频流。 它将未压缩的视频转换为压缩格式,反之亦然。 要创建 AVI 或 MP4 格式,请使用以下fourcc规范

    • AVI: cv2.VideoWriter_fourcc('M','J','P','G')
    • MP4: cv2.VideoWriter_fourcc(*'XVID')

python

# Initialize video writer object
output = cv2.VideoWriter('Resources/output_video_from_file.avi', cv2.VideoWriter_fourcc('M','J','P','G'), 20, frame_size)

c++

//Initialize video writer object
VideoWriter output("Resources/output.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'),frames_per_second, frame_size);
  • 下面以每秒 20 帧的速度将 AVI 视频文件写入磁盘

    python

    while(vid_capture.isOpened()):
        # vid_capture.read() methods returns a tuple, first element is a bool 
        # and the second is frame
    
        ret, frame = vid_capture.read()
        if ret == True:
               # Write the frame to the output files
               output.write(frame)
        else:
             print(‘Stream disconnected’)
               break
    

    c++

    while (vid_capture.isOpened())
    {
            // Initialize frame matrix
            Mat frame;
    
              // Initialize a boolean to check if frames are there or not
            bool isSuccess = vid_capture.read(frame);
    
            // If frames are not there, close it
            if (isSuccess == false)
            {
                cout << "Stream disconnected" << endl;
                break;
            }
    
    
                // If frames are present
            if(isSuccess == true)
            {
                //display frames
                output.write(frame);
                      // display frames
                      imshow("Frame", frame);
    
                      // wait for 20 ms between successive frames and break        
                      // the loop if key q is pressed
                      int key = waitKey(20);
                      if (key == ‘q’)
                      {
                          cout << "Key q key is pressed by the user. 
                          Stopping the video" << endl;
                          break;
                      }
            }
     }
    
  • 最后,释放video capture和video-writer

    python

    # Release the objects
    vid_capture.release()
    output.release()
    

    c++

    // Release the objects
    vid_capture.release();
    output.release();
    

使用opencv调整图像大小

C++和Python调整图像代码

C++

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

int main()
{
    //读取图像
    Mat image = cv::imread("../1.jpg");
    imshow("original image",image);

    //image.rows表示图片的高度,image.cols表示图片的宽度
    cout << "Original Height and Width :" << image.rows << "x" << image.cols << endl;

    //将图片缩小到300x200
    int down_width = 300;
    int down_height = 200;

    Mat resized_down;
    //将缩小后的图片保存到resized_down中
    //resize()函数第一个参数是原始图片,第二个参为转换后保存的图像,第三个参数为缩放后的大小,第四个参数为插值方法,默认为INTER_LINEAR(双线性插值)
    resize(image,resized_down,Size(down_width,down_height),INTER_LINEAR);

    //将图片放大到700x400
    int up_width = 700;
    int up_height = 400;

    Mat resized_up;
    //将放大后的图片保存到resized_up中
    resize(image,resized_up,Size(up_width,up_height),INTER_NEAREST);

    imshow("Resized Down by defining height and width", resized_down);
    imshow("Resized Up image by defining height and width", resized_up);
    waitKey();
    destroyAllWindows();
    return 0;
}

Python

# let's start with the Imports 
import cv2
import numpy as np

# Read the image using imread function
image = cv2.imread('image.jpg')
cv2.imshow('Original Image', image)

# let's downscale the image using new  width and height
down_width = 300  # 可以通过h,w,c=image.shape返回图片height,wight, number of channels
down_height = 200
down_points = (down_width, down_height)
resized_down = cv2.resize(image, down_points, interpolation= cv2.INTER_LINEAR)

# let's upscale the image using new  width and height
up_width = 600
up_height = 400
up_points = (up_width, up_height)
resized_up = cv2.resize(image, up_points, interpolation= cv2.INTER_LINEAR)

# Display images
cv2.imshow('Resized Down by defining height and width', resized_down)
cv2.waitKey()
cv2.imshow('Resized Up image by defining height and width', resized_up)
cv2.waitKey()

#press any key to close the windows
cv2.destroyAllWindows()

使用opencv裁剪图像

图像裁剪C++和Python代码

C++

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

int main()
{
  // Read image
  Mat img = imread("../1.jpg");
  //img.size().width == img.cols    img.size().height == img.rows
  cout << "Width : " << img.size().width << endl;
  cout << "Height: " << img.size().height << endl;
  cout <<"Channels: :" << img.channels() << endl;
  // 裁剪图片
  // img(Range(80,280), Range(150,330)),将图片高度从80到280,宽度从150到330的范围内裁剪出来
  Mat cropped_image = img(Range(80,280), Range(150,330));
  cout << "cropped_image Width : " << cropped_image.size().width << endl;
  cout << "cropped_image Height: " << cropped_image.size().height << endl;
  cout << "cropped_image Channels: :" << cropped_image.channels() << endl;
 
  //display image
  imshow(" Original Image", img);
  imshow("Cropped Image", cropped_image);
 
  //Save the cropped Image
  imwrite("Cropped Image.jpg", cropped_image);
 
  // 0 means loop infinitely
  waitKey(0);
  destroyAllWindows();
  return 0;
}

Python

# Import packages
import cv2
import numpy as np

img = cv2.imread('test.jpg')
print(img.shape) # Print image shape
cv2.imshow("original", img)

# Cropping an image  cropped=img[start_row:end_row, start_col:end_col]
cropped_image = img[80:280, 150:330]

# Display cropped image
cv2.imshow("cropped", cropped_image)

# Save the cropped image
cv2.imwrite("Cropped Image.jpg", cropped_image)

cv2.waitKey(0)
cv2.destroyAllWindows()
图片裁成小块C++和Python代码

Python

img =  cv2.imread("test_cropped.jpg")
image_copy = img.copy() 
imgheight=img.shape[0]
imgwidth=img.shape[1]

M = 76
N = 104
x1 = 0
y1 = 0

for y in range(0, imgheight, M):
    for x in range(0, imgwidth, N):
        if (imgheight - y) < M or (imgwidth - x) < N:
            break
            
        y1 = y + M
        x1 = x + N

        # check whether the patch width or height exceeds the image width or height
        if x1 >= imgwidth and y1 >= imgheight:
            x1 = imgwidth - 1
            y1 = imgheight - 1
            #Crop into patches of size MxN
            tiles = image_copy[y:y+M, x:x+N]
            #Save each patch into file directory
            cv2.imwrite('saved_patches/'+'tile'+str(x)+'_'+str(y)+'.jpg', tiles)
            cv2.rectangle(img, (x, y), (x1, y1), (0, 255, 0), 1)
        elif y1 >= imgheight: # when patch height exceeds the image height
            y1 = imgheight - 1
            #Crop into patches of size MxN
            tiles = image_copy[y:y+M, x:x+N]
            #Save each patch into file directory
            cv2.imwrite('saved_patches/'+'tile'+str(x)+'_'+str(y)+'.jpg', tiles)
            cv2.rectangle(img, (x, y), (x1, y1), (0, 255, 0), 1)
        elif x1 >= imgwidth: # when patch width exceeds the image width
            x1 = imgwidth - 1
            #Crop into patches of size MxN
            tiles = image_copy[y:y+M, x:x+N]
            #Save each patch into file directory
            cv2.imwrite('saved_patches/'+'tile'+str(x)+'_'+str(y)+'.jpg', tiles)
            cv2.rectangle(img, (x, y), (x1, y1), (0, 255, 0), 1)
        else:
            #Crop into patches of size MxN
            tiles = image_copy[y:y+M, x:x+N]
            #Save each patch into file directory
            cv2.imwrite('saved_patches/'+'tile'+str(x)+'_'+str(y)+'.jpg', tiles)
            cv2.rectangle(img, (x, y), (x1, y1), (0, 255, 0), 1)
   
#Save full image into file directory
cv2.imshow("Patched Image",img)
cv2.imwrite("patched.jpg",img)
 
cv2.waitKey()
cv2.destroyAllWindows()

C++

Mat img = imread("test_cropped.jpg");
Mat image_copy = img.clone();
int imgheight = img.rows;
int imgwidth = img.cols;

int M = 76;
int N = 104;

int x1 = 0;
int y1 = 0;
for (int y = 0; y<imgheight; y=y+M)
{
    for (int x = 0; x<imgwidth; x=x+N)
    {
        if ((imgheight - y) < M || (imgwidth - x) < N)
        {
            break;
        }
        y1 = y + M;
        x1 = x + N;
        string a = to_string(x);
        string b = to_string(y);

        if (x1 >= imgwidth && y1 >= imgheight)
        {
            x = imgwidth - 1;
            y = imgheight - 1;
            x1 = imgwidth - 1;
            y1 = imgheight - 1;

            // crop the patches of size MxN
            Mat tiles = image_copy(Range(y, imgheight), Range(x, imgwidth));
            //save each patches into file directory
            imwrite("saved_patches/tile" + a + '_' + b + ".jpg", tiles);  
            rectangle(img, Point(x,y), Point(x1,y1), Scalar(0,255,0), 1);    
        }
        else if (y1 >= imgheight)
        {
            y = imgheight - 1;
            y1 = imgheight - 1;

            // crop the patches of size MxN
            Mat tiles = image_copy(Range(y, imgheight), Range(x, x+N));
            //save each patches into file directory
            imwrite("saved_patches/tile" + a + '_' + b + ".jpg", tiles);  
            rectangle(img, Point(x,y), Point(x1,y1), Scalar(0,255,0), 1);    
        }
        else if (x1 >= imgwidth)
        {
            x = imgwidth - 1;   
            x1 = imgwidth - 1;

            // crop the patches of size MxN
            Mat tiles = image_copy(Range(y, y+M), Range(x, imgwidth));
            //save each patches into file directory
            imwrite("saved_patches/tile" + a + '_' + b + ".jpg", tiles);  
            rectangle(img, Point(x,y), Point(x1,y1), Scalar(0,255,0), 1);    
        }
        else
        {
            // crop the patches of size MxN
            Mat tiles = image_copy(Range(y, y+M), Range(x, x+N));
            //save each patches into file directory
            imwrite("saved_patches/tile" + a + '_' + b + ".jpg", tiles);  
            rectangle(img, Point(x,y), Point(x1,y1), Scalar(0,255,0), 1);    
        }
    }
}

imshow("Patched Image", img);
imwrite("patched.jpg",img);
waitKey();
destroyAllWindows();

使用 opencv进行图像旋转和平移

C++和Python旋转代码

C++

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

int main()
{
    Mat img = imread("../1.jpg");
    imshow("img",img);

    double angle = 45;

    Point2d center((img.cols-1)/2.0,(img.rows-1)/2.0);

    //getRotationMatrix2D()函数 center:输入图像的旋转中心,angle: 以度为单位的旋转角度,scale:各向同性比例因子,根据提供的值放大或缩小图像
    //如果angle为正,则图像逆时针方向旋转。如果要将图像顺时针旋转相同的量,则angle需要为负值。
    Mat rotation_matix = getRotationMatrix2D(center, angle, 1.0);

    Mat rotated_image;

    //warpAffine()函数对图像应用仿射变换,应用仿射变换后,原始图像中的所有平行线在输出图像中也将保持平行。
    //img 是输入的原始图像,rotated_image 是输出的旋转后的图像,矩阵 rotation_matix 应用变换, img.size()输出图片的大小。
    warpAffine(img, rotated_image, rotation_matix, img.size());
    imshow("rotated image", rotated_image);

    waitKey(0);
    imwrite("rotated_imag.jpg",rotated_image);
    return 0;
}

Python

import cv2

# Reading the image
image = cv2.imread('image.jpg')

# dividing height and width by 2 to get the center of the image
height, width = image.shape[:2]
# get the center coordinates of the image to create the 2D rotation matrix
center = (width/2, height/2)

# using cv2.getRotationMatrix2D() to get the rotation matrix(得到2D选择矩阵)
rotate_matrix = cv2.getRotationMatrix2D(center=center, angle=45, scale=1)

# rotate the image using cv2.warpAffine(得到旋转的图像)
rotated_image = cv2.warpAffine(src=image, M=rotate_matrix, dsize=(width, height))

cv2.imshow('Original image', image)
cv2.imshow('Rotated image', rotated_image)
# wait indefinitely, press any key on keyboard to exit
cv2.waitKey(0)
# save the rotated image to disk
cv2.imwrite('rotated_image.jpg', rotated_image)
C++和Python平移代码

C++

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

int main()
{
    Mat img = imread("../1.jpg");
    cout<<img.size().width<<endl;
    cout<<img.size().height<<endl;

    //cols是列数(宽度),rows是行数(高度)
    float width = img.cols;
    float height = img.rows;

    float tx = width/4;
    float ty = height/4;

    //让图像需要移动的像素为tx和ty。M = [1  0  tx    提供正值tx将使图像向右移动,负值将使图像向左移动。
    //                               0  1  ty]   正值ty将使图像向下移动,而负值将使图像向上移动。
    float warp_values[] = {1.0,0.0,tx,0.0,1.0,ty};
    //将warp_values转换为2行3列的二维数组 
    Mat translation_matrix = Mat(2,3,CV_32F,warp_values);

    Mat translated_img;
    //warpAffine()是一个通用函数,可用于对图像应用任何类型的仿射变换。只需适当地定义矩阵 M 即可。
    warpAffine(img, translated_img, translation_matrix,img.size());

    imshow("Translated image", translated_img);
    imshow("Original image", img);
    waitKey(0);
    // save the translated image to disk
    imwrite("translated_image.jpg", translated_img);


    return 0;
}

Python

#include "opencv2/opencv.hpp"
using namespace cv
// read the image 
Mat image = imread("image.jpg");
// get the height and width of the image
int height = image.cols;
int width = image.rows;

// get tx and ty values for translation
float tx = float(width) / 4;
float ty = float(height) / 4;
// create the translation matrix using tx and ty
float warp_values[] = { 1.0, 0.0, tx, 0.0, 1.0, ty };
Mat translation_matrix = Mat(2, 3, CV_32F, warp_values);

// save the resulting image in translated_image matrix
Mat translated_image;
// apply affine transformation to the original image using the translation matrix
warpAffine(image, translated_image, translation_matrix, image.size());

//display the original and the Translated images
imshow("Translated image", translated_image);
imshow("Original image", image);
waitKey(0);
// save the translated image to disk
imwrite("translated_image.jpg", translated_image);

使用opencv注释图像

C++总代码

C++

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

int main()
{
    Mat img = cv::imread("../1.jpg");
    cv::imshow("img",img);

    if(img.empty())
    {
        cout<<"Image not read"<<endl;
        return -1;
    }
    //画一条线
    Mat imageLine = img.clone();
    Point point1(200,80);
    Point point2(350,80);     
    // line()函数,第一个参数是图像,接下来的两个参数是直线的起点和终点,后面有个参数是线的颜色,2为线的厚度,8为线的类型
    line(imageLine,point1,point2,Scalar(0,0,255),2,8,0);
    imshow("line",imageLine);

    //画一个圆
    Mat imageCircle = img.clone();
    Point circleee_center(380,180);
    int  radius  = 20;
    //circle()函数,第一个参数是图像,接下来两个参数是圆的中点和半径,后面有个参数是圆的颜色,-1为实心圆(如果是正数这是圆线的厚度)
    circle(imageCircle,circleee_center,radius,Scalar(0,255,0),-1,8,0);
    imshow("circle",imageCircle);
    
    //画一个矩形
    Mat imageRect = img.clone();
    Point point1Rect(100,200);
    Point point2Rect(300,250);
    //rectangle()函数,第一个参数是图像,接下来两个参数是矩形的起点和终点
    rectangle(imageRect,point1Rect,point2Rect,Scalar(0,255,255),2,8,0);         
    imshow("rect",imageRect);

    //画一个椭圆,半椭圆
    Mat imageEllipse = img.clone();
    Point centerEllipse1(400,150);
    Point centerEllipse2(200,200);
    //axis()函数,第一个参数是椭圆的长轴,第二个参数是椭圆的短轴
    Point axis1(100,50);
    Point axis2(100,50);
    Point axis3(100,50);
    //ellipse()函数,第一个参数是图像,接下来两个参数是椭圆的中心点,第三个参数是椭圆的长轴和短轴,第四个参数是角度,后面两个参数是画一个完整的椭圆0到360度
    ellipse(imageEllipse,centerEllipse1,axis1,0,0,360,Scalar(0,255,255),2,8,0);
    //90表示椭圆旋转了90度,也就是从水平方向变成了垂直方向
    ellipse(imageEllipse,centerEllipse1,axis2,90,0,360,Scalar(0,255,255),2,8,0);
    //0,180;180,360是画半圆
    ellipse(imageEllipse,centerEllipse2,axis3,0,0,180,Scalar(0,0,255),-2,8,0);
    ellipse(imageEllipse,centerEllipse2,axis3,0,180,360,Scalar(0,0,255),3,8,0);
    imshow("ellipse",imageEllipse);

    //添加文字
    Mat imageText = img.clone();
    //putText()函数,第一个参数是图像,接下来两个参数是文本内容,和文本的起始位置,第三个参数是字体的设置,3为字体的大小
    putText(imageText, "Hello, OpenCv!", Point(200, 100), FONT_HERSHEY_DUPLEX, 1, Scalar(0,0,255));
    imshow("text", imageText);      

    waitKey(0);
    return 0;
}
Python画彩色线条
  • 画彩色线条:line(image, start_point, end_point, color, thickness)
# Import dependencies
import cv2
# Read Images
img = cv2.imread('sample.jpg')
# Display Image
cv2.imshow('Original Image',img)
cv2.waitKey(0)
# Print error message if image is null
if img is None:
    print('Could not read image')
# Draw line on image
imageLine = img.copy()  # 进行拷贝图片
# Draw the image from point A to B
pointA = (200,80)
pointB = (450,80)
# 左上角是原始的点,x 轴代表图像的水平方向 y轴代表图像的垂直方向
# 其中imageLine是原始的图片, 开始点,结束点,线条的颜色,线条粗细,
cv2.line(imageLine, pointA, pointB, (255, 255, 0), thickness=3, lineType=cv2.LINE_AA)
cv2.imshow('Image Line', imageLine)
cv2.waitKey(0)
Python画圆(实心圆)
  • 画圆:circle(image, center_coordinates, radius, color, thickness)
    • 参数分别是图片,中心点,半径,颜色,线条粗细,thickness=-1为实心圆
# Make a copy of image
imageCircle = img.copy()
# define the center of circle
circle_center = (415,190)
# define the radius of the circle
radius =100
#  Draw a circle using the circle() Function
cv2.circle(imageCircle, circle_center, radius, (0, 0, 255), thickness=3, lineType=cv2.LINE_AA) 
# Display the result
cv2.imshow("Image Circle",imageCircle)
cv2.waitKey(0)
Python画矩形
  • 画一个矩形:rectangle(image, start_point, end_point, color, thickness)
    • start_point: (top, left) end_point: (bottom, right)
# make a copy of the original image
imageRectangle = img.copy()
# define the starting and end points of the rectangle
start_point =(300,115)
end_point =(475,225)
# draw the rectangle
cv2.rectangle(imageRectangle, start_point, end_point, (0, 0, 255), thickness= 3, lineType=cv2.LINE_8) 
# display the output
cv2.imshow('imageRectangle', imageRectangle)
cv2.waitKey(0)
Python添加文本
  • 添加文本:putText(image, text, org, font, fontScale, color)
    • image: 原始图片 text: 需要标注的文本
    • org: 文本处在的(top, left)坐标
    • fontFace: OpenCV 支持 Hershey 字体集合中的几种字体样式,以及斜体字体。 如下:
      • FONT_HERSHEY_SIMPLEX = 0,
      • FONT_HERSHEY_PLAIN = 1,
      • FONT_HERSHEY_DUPLEX = 2,
      • FONT_HERSHEY_COMPLEX = 3,
      • FONT_HERSHEY_TRIPLEX = 4,
      • FONT_HERSHEY_COMPLEX_SMALL = 5,
      • FONT_HERSHEY_SCRIPT_SIMPLEX = 6,
      • FONT_HERSHEY_SCRIPT_COMPLEX = 7,
      • FONT_ITALIC = 16
    • fontScale: 字体比例是一个浮点值,用于向上或向下缩放字体的基本大小。 根据图像的分辨率,选择适当的字体比例。
    • color: 这里是一个BGR元组(B, G, R)
# make a copy of the original image
imageText = img.copy()
#let's write the text you want to put on the image
text = 'I am a Happy dog!'
#org: Where you want to put the text
org = (50,350)
# write the text on the input image
# 原始图片 文本 左上角 字体样式 字体缩放比例 字体颜色
cv2.putText(imageText, text, org, fontFace=cv2.FONT_HERSHEY_COMPLEX, fontScale=1.5, color=(250,225,100))

# display the output image with text over it
cv2.imshow("Image Text",imageText)
cv2.waitKey(0)
cv2.destroyAllWindows()

使用OpenCV-扩充图像边界cv::copyMakeBorder

使用比例因子调整图像大小
  • INTER_AREA : 使用像素区域关系进行重采样。 这最适合减小图像的大小(缩小)。 当用于放大图像时,它使用 INTER_NEAREST 方法。
  • INTER_CUBIC: 这使用双三次插值来调整图像大小。 在调整大小和插入新像素时,此方法作用于图像的 4×4 相邻像素。 然后取 16 个像素的权重平均值来创建新的插值像素。
  • INTER_LINEAR: 这种方法有点类似于 INTER_CUBIC 插值。 但与 INTER_CUBIC 不同,它使用 2×2 相邻像素来获得插值像素的加权平均值。
  • INTER_NEAREST: INTER_NEAREST 方法使用最近邻概念进行插值。 这是最简单的方法之一,仅使用图像中的一个相邻像素进行插值。

C++和Python代码

C++

# Scaling Down the image 0.6 using different Interpolation Method
Mat res_inter_linear, res_inter_nearest, res_inter_area;
resize(image, res_inter_linear, Size(), scale_down, scale_down, INTER_LINEAR);
resize(image, res_inter_nearest, Size(), scale_down, scale_down, INTER_NEAREST);
resize(image, res_inter_area, Size(), scale_down, scale_down, INTER_AREA);

Mat a,b,c;
vconcat(res_inter_linear, res_inter_nearest, a);
vconcat(res_inter_area, res_inter_area, b);
vconcat(a, b, c);
// Display the image Press any key to continue
imshow("Inter Linear :: Inter Nearest :: Inter Area :: Inter Area", c);

Python

# Scaling Down the image 0.6 times using different Interpolation Method
res_inter_nearest = cv2.resize(image, None, fx= scale_down, fy= scale_down, interpolation= cv2.INTER_NEAREST)
res_inter_linear = cv2.resize(image, None, fx= scale_down, fy= scale_down, interpolation= cv2.INTER_LINEAR)
res_inter_area = cv2.resize(image, None, fx= scale_down, fy= scale_down, interpolation= cv2.INTER_AREA)

# Concatenate images in horizontal axis for comparison
vertical= np.concatenate((res_inter_nearest, res_inter_linear, res_inter_area), axis = 0)
# Display the image Press any key to continue
cv2.imshow('Inter Nearest :: Inter Linear :: Inter Area', vertical)
posted @ 2023-06-06 15:41  俗俗俗  阅读(62)  评论(0编辑  收藏  举报