opencv系列记录

opencv系列记录(持续更新)

记录并汇总学习和解决问题过程中遇到方法方案



图像变换

逐步汇总

=== 基础 ===

图像就是矩阵,图像变换就是矩阵变换,关键是得到变换矩阵。
参考这里

opencv得到变换矩阵的几个方法:

  1. cv2.getRotationMatrix2D(center,degree,scale)
  2. 比较两组坐标点points1points2
    – 选取3个点仿射变换
    cv2.getAffineTransform(points1,points2)
    – 选取4个点透视变换
    cv2.getPerspectiveTransform(points1,points2)
  3. 自己指定变换矩阵matrix

=== 例子===

  1. cv2.getRotationMatrix2D(center,degree,scale)
##################### 对图像进行变换(旋转)
import cv2
img = cv2.imread('cat.jpg')
rows,cols,_ = img.shape

#1.得到变换矩阵
#参数 (center),degree, scale
matrix = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
#2.变换
img1 = cv2.warpAffine(img,matrix,(cols,rows))

cv2.imshow('img',img)
cv2.imshow('img1',img1)
  1. 比较两组坐标点points1points2
import numpy as np
#####3个点
points1 = np.float32([[50,50],[200,50],[50,200]])
points2 = np.float32([[10,100],[200,50],[100,250]])
#1.得到变换矩阵
matrix = cv2.getAffineTransform(points1,points2)
#2. 变换
output = cv2.warpAffine(img,matrix,(cols,rows))


#####4个点透视变换
points1 = np.float32([[50,50],[200,50],[50,200],[200,200]])
points2 = np.float32([[10,100],[200,50],[100,250],[150,260])
#1.得到变换矩阵
matrix = cv2.getPerspectiveTransform(points1,points2)
#2. 变换
output = cv2.warpPerspective(img, matrix, (cols, rows))

判断2线段相交

参考这里

最直接的方法就是直接计算两条直线的交点,然后看看交点是否分别在这两条线段上。这样的方法很容易理解,但是代码实现比较麻烦。

另一种常用的方法是通过向量叉积来判断的,这种方法不需要算出直线方程,在代码实现上比较简便。
用这种方法判别线段是否相交一般分为两步:

  1. 快速排斥实验
  2. 跨立实验
struct Line {
    double x1;
    double y1;
    double x2;
    double y2;
};

bool intersection(const Line &l1, const Line &l2)
{
    //快速排斥实验
    if ((l1.x1 > l1.x2 ? l1.x1 : l1.x2) < (l2.x1 < l2.x2 ? l2.x1 : l2.x2) ||
        (l1.y1 > l1.y2 ? l1.y1 : l1.y2) < (l2.y1 < l2.y2 ? l2.y1 : l2.y2) ||
        (l2.x1 > l2.x2 ? l2.x1 : l2.x2) < (l1.x1 < l1.x2 ? l1.x1 : l1.x2) ||
        (l2.y1 > l2.y2 ? l2.y1 : l2.y2) < (l1.y1 < l1.y2 ? l1.y1 : l1.y2))
    {
        return false;
    }
    //跨立实验
    if ((((l1.x1 - l2.x1)*(l2.y2 - l2.y1) - (l1.y1 - l2.y1)*(l2.x2 - l2.x1))*
        ((l1.x2 - l2.x1)*(l2.y2 - l2.y1) - (l1.y2 - l2.y1)*(l2.x2 - l2.x1))) > 0 ||
        (((l2.x1 - l1.x1)*(l1.y2 - l1.y1) - (l2.y1 - l1.y1)*(l1.x2 - l1.x1))*
        ((l2.x2 - l1.x1)*(l1.y2 - l1.y1) - (l2.y2 - l1.y1)*(l1.x2 - l1.x1))) > 0)
    {
        return false;
    }
    return true;
}
————————————————
版权声明:本文为CSDN博主「Siannodel_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq826309057/article/details/70942061

opencv Mat类

参考这里

  1. 构造函数
cv::Mat::Mat()
cv::Mat::Mat(int rows,int cols,int type)
cv::Mat::Mat(Size size,int type ) 
cv::Mat::Mat(const Mat & m)


cv::Mat a ; //默认构造函数,创建矩阵头
a = cv::imread("test.jpg");//读入图像,矩阵指针指向该像素数据
cv::Mat b = a ;//引用复制 
  1. 成员函数
Mat src = imread("test.jpg");
int elem = src.at<int>(0,0);

Mat image2 = image1.clone();//重新复制克隆

image.convertTo(CV_32FC3);

Mat image3;
image1.copyTo(image3);
  1. 成员变量
int cv::Mat::cols
int cv::Mat::rows

uchar* cv::Mat::data // 指向矩阵的数据单元的指针
int cv::Mat::dims // 返回矩阵维度,该维度≥2

MatSize cv::Mat::size // 返回矩阵大小

opencv bounding rect

参考这里

矩形边框(Bounding Rectangle)是说,用一个最小的矩形,把找到的形状包起来。还有一个带旋转的矩形,面积会更小

# 用绿色(0, 255, 0)来画出最小的矩形框架
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)

# 用红色表示有旋转角度的矩形框架
rect = cv2.minAreaRect(cnt)
box = cv2.cv.BoxPoints(rect)
box = np.int0(box)
cv2.drawContours(img, [box], 0, (0, 0, 255), 2)
cv2.imwrite('contours.png', img)

cv2,numpy图片操作

参考这里

from PIL import Image
img = Image.open('examples.png')
img = np.array(img)     # 将PIL格式图片转为numpy格式

plt.imshow(Image.open('examples.png'))    # 实际上plt.imshow可以直接显示PIL格式图像

cv2.imread()度

import cv2
#已经是np.array了
img = cv2.imread('examples.png')    # 默认是读入为彩色图,即使原图是灰度图也会复制成三个相同的通道变成彩色图

plt.imshow(img[..., -1::-1])    # 因为opencv读取进来的是bgr顺序呢的,而imshow需要的是rgb顺序,因此需要先反过来

OpenCV图像剪裁扩展

参考这里
利用感兴趣区域ROI和矩形类Rect

剪裁

cv::Mat src = cv::imread("D:\\OpencvTest\\1.jpg");//原始图像是200*200  
cv::Rect rect(-100, -100, 500, 500);  
cv::Mat image = src(rect);//这时裁剪,必然出错
————————————————
版权声明:本文为CSDN博主「pan_jinquan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/guyuealian/article/details/78113325

检查发现越界的话需要填充
OpenCV3中提供了一个图像边界的函数cv::copyMakeBorder(对应opencv2中的cvCopyMakeBorder)以及borderInterpolate

OpenCV 用 VideoWriter 创建视频

参考这里

'''
获取摄像头的视频流,然后保存到本地,帧率是 20fps,尺寸是 1920x1080.
'''
import numpy as np
import cv2

cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('testwrite.avi',fourcc, 20.0, (1920,1080),True)

while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:
        cv2.imshow('frame',frame)
        out.write(frame)
        if cv2.waitKey(10) & 0xFF == ord('q'):
            break
    else:
        break

cap.release()
out.release()
cv2.destroyAllWindows()

linux opencv源码编译安装

参考这里opencv官网linux tutorial安装

  1. Build core modules
# Install minimal prerequisites (Ubuntu 18.04 as reference)
sudo apt update && sudo apt install -y cmake g++ wget unzip
# Download and unpack sources
wget -O opencv.zip https://github.com/opencv/opencv/archive/master.zip
unzip opencv.zip
# Create build directory
mkdir -p build && cd build
# Configure
cmake  ../opencv-master
# Build
cmake --build .
  1. Install
sudo make install

涉及pkg-config

pkg-confg的命令和作用参考这里

编译使用opencv的程序时,经常要调用OpenCV一系列库才能成功编译通过,pkg-config经常出现在makefile里用于编译时方便获取opencv必要的一系列库文件位置

下面是opencv,找不到pkg-config时的解决方式,手动添加.pc文件

#注意opencv.pc的路径
cd /usr/local/lib
sudo mkdir pkgconfig
cd pkgconfig
sudo touch opencv.pc

opencv.pc里面添加如下信息

#opencv.pc里面添加如下信息
prefix=/usr/local
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib

Name: opencv
Description: The opencv library
Version:4.0.1
Cflags: -I${includedir}/opencv4
Libs: -L${libdir} -lopencv_stitching -lopencv_objdetect -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_ml -lopencv_imgproc -lopencv_flann  -lopencv_core

保存退出后,导入环境变量

export  PKG_CONFIG_PATH=/usr/local/lib/pkgconfig

下面是简洁的opencv makefile的示例

#######
# simple opencv makefile
#######
CXX ?=g++
OPENCV_INCLUDE=/usr/local/include/opencv4 #this is opencv header file path
LDFLAGS += $(shell pkg-config --cflags --libs opencv) #this are dynamic libs for -llib, use pke-config


SRC_CPP=./test_cv.cpp
SRC_EXE=./test

${SRC_EXE}:
	${CXX} -o $@ ${SRC_CPP} -I${OPENCV_INCLUDE} ${LDFLAGS}

all: ${SRC_EXE}

clean:
	rm -rf ${SRC_EXE}

cv2/PIL read bytearray buffer

import cv2
from PIL import Image
import io
import numpy as np

def get_bytesarray(path):
    imgbyte=bytearray()
    with open(path,'rb') as f:
        imgbyte=f.read() #以binary方式读入imgbyte
    print('len(imgbyte) ',len(imgbyte))
    return imgbyte

def bytesarrayToImg(imgbyte):
    nparray=np.frombuffer(imgbyte,np.uint8) #使用np.uint8
    print(nparray)
    print(nparray.shape)
    img = cv2.imdecode(nparray, cv2.COLOR_RGBA2BGR) #cv2的RGB通道是反过来的
    print(img.shape)
    img=Image.fromarray(img) #进入PIL Image中进行图像操作/显示
    img.show()


if __name__=="__main__":
    path='./img.jpg'
    imgbyte=get_bytesarray(path)
    bytesarrayToImg(imgbyte)


总结

这里对文章进行总结:

其他参考材料
超详细的OpenCV入门教程

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值