【OpenCV C++&Python】(三)改变颜色空间、图像的几何变换

简介:

改变颜色空间、图像的几何变换

Python

改变颜色空间

OpenCV有150多种颜色空间转换方法,其中常用的方法是:BGR↔ Gray和BGR↔ HSV。

对于颜色转换,我们使用函数cv.cvtColor(input_image, flag)实现,其中flag决定转换的类型。

对于BGR→ Gray转换,我们使用flag:cv.COLOR_BGR2GRAY。 BGR → HSV则使用 cv.COLOR_BGR2HSV。要获取其他flag,只需在Python终端中运行以下命令:

import cv2 as cv
flags = [i for i in dir(cv) if i.startswith('COLOR_')]
print( flags )

注意: OpenCV中,HSV的色调(H)范围为[0, 179],饱和度(S)范围为[0, 255],值(V)范围为[0, 255]。不同的软件使用不同的范围。因此,如果要将OpenCV的HSV值与它们进行比较,则需要规范化这些范围。

提取彩色对象:

在HSV表示颜色比BGR颜色空间更容易。现在我们知道了如何将BGR图像转换为HSV,我们可以使用它来提取彩色对象。下面,我们将尝试提取图中深蓝色瓶盖:

如何找到要定位颜色的HSV值?

你只需传递所需的BGR值给 cv.cvtColor()。例如,查找蓝色的HSV值:

import cv2 as cv
import numpy as np

blue = np.uint8([[[255, 0, 0]]])
hsv_blue = cv.cvtColor(blue, cv.COLOR_BGR2HSV)
print(hsv_blue)
[[[120 255 255]]]

不断调整后取[120-10, 60,60] [120+10, 255, 255] 作为下界和上界。

image = cv.imread('cap.jpg')
#  将图像从BGR转换到HSV颜色空间
hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
# 定义HSV中蓝色的下界和上界
lower_blue = np.array([110, 60, 60])
upper_blue = np.array([130, 255, 255])
# [lower_blue,upper_blue]内的像素为255,其他为0
mask = cv.inRange(hsv, lower_blue, upper_blue)
# 对mask和image按位和  提取深蓝色瓶盖
res = cv.bitwise_and(image, image, mask=mask)
cv.imshow('image', image)
cv.imshow('mask', mask)
cv.imshow('res', res)
k = cv.waitKey(0)
cv.destroyAllWindows()

图像的几何变换

OpenCV提供了两个变换函数:cv.warpAffine cv.warpPerspective,使用它们可以执行各种变换。cv.warpAffine 使用2x3的变换矩阵,而 cv.warpPerspective将3x3变换矩阵作为输入。

缩放

OpenCV的cv.resize() 用于缩放图像。有多种插值方法:cv.INTER_AREA用于收缩,cv.INTER_CUBIC (slow)和 cv.INTER_LINEAR用于放大。默认情况下,插值方法为 cv.INTER_LINEAR。可以通过指定倍数或指定大小调整图像大小的方法:

import cv2 as cv
# 指定倍数
img = cv.imread('image.jpg')
res1 = cv.resize(img, None, fx=0.5, fy=0.5, interpolation=cv.INTER_AREA)  
# 或者:指定大小
height, width = img.shape[:2]
res2 = cv.resize(img, (int(1.5 * width), int(1.5 * height)), interpolation=cv.INTER_CUBIC)  
cv.imshow('res1', res1)
cv.imshow('res2', res2)
k = cv.waitKey(0)
cv.destroyAllWindows()

平移

平移是物体位置的移动。如果知道$(x, y)$方向上的偏移$(t_x,t_y)$,则可以按如下方式创建平移矩阵$M$:

$$ M=\left[\begin{array}{lll} 1 & 0 & t_{x} \\ 0 & 1 & t_{y} \end{array}\right] $$

你可以将$M$放入np.float32的Numpy数组中。并将其传递到 cv.warpAffine()函数。以下给出有关(100,50)移位的示例:

import numpy as np
import cv2 as cv

img = cv.imread('idiot.jpg')
rows, cols, _ = img.shape
M = np.float32([[1, 0, 100], [0, 1, 50]])
dst = cv.warpAffine(img, M, (cols, rows))  
cv.imshow('img', dst)  
cv.waitKey(0)
cv.destroyAllWindows()

cv.warpAffine()的第三个参数是输出图像的大小,其形式应为 (宽度、高度) 。记住宽度=列数,高度=行数。

旋转

旋转角度为$θ$的变换矩阵为

$$ M=\left[\begin{array}{cc} \cos \theta & -\sin \theta \\ \sin \theta & \cos \theta \end{array}\right] $$

但OpenCV提供了具有可调旋转中心的缩放旋转,可以在任何位置$( { center. } x, { center. } y)$旋进行转。修改后的变换矩阵如下所示:

$$ \left[\begin{array}{ccc} \alpha & \beta & (1-\alpha) \cdot { center. } x-\beta \cdot { center. } y \\ -\beta & \alpha & \beta \cdot { center. } x+(1-\alpha) \cdot { center. } y \end{array}\right] $$

其中:

$$ \begin{array}{l} \alpha= { scale } \cdot \cos \theta \\ \beta= { scale } \cdot \sin \theta \end{array} $$

OpenCV提供了一个函数 cv.getRotationMatrix2D来得到这个变换矩阵。下面的示例将图像相对于中心旋转90度($\theta=90$)而不进行任何缩放($scale=1$)。

import cv2 as cv
img = cv.imread('image.jpg')
rows, cols, _ = img.shape
# (旋转的中心点x,旋转的中心点y,旋转的角度,图像缩放因子)
M = cv.getRotationMatrix2D(((cols - 1) / 2.0, (rows - 1) / 2.0), 90, 1)
dst = cv.warpAffine(img, M, (cols, rows))
cv.imshow('img', dst)
cv.waitKey(0)
cv.destroyAllWindows()

仿射变换

在仿射变换中,原始图像中的所有平行线在输出图像中仍然是平行的。为了找到变换矩阵,我们需要从输入图像中选取三个点并指定其在输出图像中的相应位置,然后传递给cv.getAffineTransform创建一个2x3矩阵,最后该该矩阵将传递cv.warpAffine进行变换。

import cv2 as cv
import numpy as np

img = cv.imread('affine.jpg')
rows, cols, ch = img.shape
img[45:55, 45:55, :] = [255, 0, 0]
img[195:205, 45:55, :] = [0, 255, 0]
img[45:55, 195:205, :] = [0, 0, 255]
pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
pts2 = np.float32([[10, 100], [200, 50], [100, 250]])
M = cv.getAffineTransform(pts1, pts2)
dst = cv.warpAffine(img, M, (cols, rows))
cv.imshow('img', img)
cv.imshow('dst', dst)
cv.waitKey(0)


透视变换

对于透视变换,需要输入图像上的4个点和输出图像上的相应点来得到变换矩阵,且在这4个点中,有3个不应共线。在OpenCV中可以使用 cv.getPerspectiveTransform求出该变换矩阵,然后使用cv.warpPerspective应用这个变换矩阵。

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

img = cv.imread('perspective.jpg')

rows, cols, ch = img.shape
pts1 = np.float32([[290, 139], [362, 121], [331, 209], [409, 191]])
pts2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])
M = cv.getPerspectiveTransform(pts1, pts2)
dst = cv.warpPerspective(img, M, (300, 300))  //

cv.imshow('img', img)
cv.imshow('dst', dst)
cv.waitKey(0)

C++

改变颜色空间

#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
    Mat image = imread("cap.jpg");
    // 将图像从BGR转换到HSV颜色空间
    Mat hsv, mask, res;
    cvtColor(image, hsv, COLOR_BGR2HSV);
    // [Scalar(110, 60, 60), Scalar(130, 255, 255)]内的像素为255,其他为0
    inRange(hsv, Scalar(110, 60, 60), Scalar(130, 255, 255),mask);
    // 对mask和image按位和  提取深蓝色瓶盖
    bitwise_and(image, image, res,mask);
    imshow("image", image);
    imshow("mask", mask);
    imshow("res", res);
    waitKey(0);
    return 0;
}

图像的几何变换

缩放

#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
    Mat img = imread("image.jpg");
    Mat res1, res2;
    // 指定倍数
    resize(img,res1, Size(),0.5,0.5,INTER_AREA);
    // 指定大小
    int height = img.rows* 1.5;
    int width = img.cols* 1.5;
    resize(img, res2, Size(width,height), 0, 0, INTER_CUBIC);
    imshow("res1", res1);
    imshow("res2", res2);
    waitKey(0);
    return 0;
}

平移

#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
    Mat img = imread("image.jpg");
    Mat dst;

    //定义平移矩阵
    Mat M = cv::Mat::zeros(2, 3, CV_32FC1);
    M.at<float>(0, 0) = 1;
    M.at<float>(0, 2) = 100; //水平平移量
    M.at<float>(1, 1) = 1;
    M.at<float>(1, 2) = 50; //竖直平移量
    warpAffine(img, dst, M, Size(img.cols,img.rows));
    imshow("dst", dst);
    waitKey(0);
    return 0;
}

旋转

#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
    Mat img = imread("image.jpg");
    Mat dst;

    //定义平移矩阵
    Mat M = getRotationMatrix2D(Point((img.cols - 1) / 2, (img.rows - 1) / 2), 90, 1);
    warpAffine(img, dst, M, Size(img.cols,img.rows));
    imshow("dst", dst);
    waitKey(0);
    return 0;
}

仿射变换

#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
    Mat img = imread("affine.jpg");
    Mat dst;
    Mat roi1 = img(Range(45, 55), Range(45, 55));
    Mat roi2 = img(Range(195, 205), Range(45, 55));
    Mat roi3 = img(Range(45, 55), Range(195, 205));
    roi1 = Scalar(255, 0, 0);
    roi2 = Scalar(0, 255, 0);
    roi3 = Scalar(0, 0, 255);
    Mat pts1 = (Mat_<float>(3, 2) << 50, 50, 200, 50, 50, 200);
    Mat pts2 = (Mat_<float>(3, 2) << 10, 100, 200, 50, 100, 250);
    Mat M = getAffineTransform(pts1, pts2);
    warpAffine(img, dst, M, Size(img.cols, img.rows));
    imshow("img", img);
    imshow("dst", dst);
    waitKey(0);
    return 0;
}

透视变换

#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
    Mat img = imread("perspective.jpg");
    Mat dst;
    Mat pts1 = (Mat_<float>(4, 2) << 290, 139, 362, 121, 331, 209, 409, 191);
    Mat pts2 = (Mat_<float>(4, 2) << 0, 0, 300, 0, 0, 300, 300, 300);
    Mat M = getPerspectiveTransform(pts1, pts2);
    warpPerspective(img, dst, M, Size(300, 300));
    imshow("img", img);
    imshow("dst", dst);
    waitKey(0);
    return 0;
}

代码:

https://gitee.com/BinaryAI/open-cv-c--and-python

参考:

[1] https://docs.opencv.org/4.5.5/index.html

相关文章
|
2月前
|
计算机视觉
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
542 0
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
|
3月前
|
算法 计算机视觉
opencv图像形态学
图像形态学是一种基于数学形态学的图像处理技术,它主要用于分析和修改图像的形状和结构。
55 4
|
3月前
|
存储 计算机视觉
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
本文介绍了使用OpenCV进行图像读取、显示和存储的基本操作,以及如何绘制直线、圆形、矩形和文本等几何图形的方法。
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
|
4月前
|
算法 计算机视觉 Python
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
该文章详细介绍了使用Python和OpenCV进行相机标定以获取畸变参数,并提供了修正图像畸变的全部代码,包括生成棋盘图、拍摄标定图像、标定过程和畸变矫正等步骤。
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
WK
|
4月前
|
编解码 计算机视觉 Python
如何在OpenCV中进行图像转换
在OpenCV中,图像转换涉及颜色空间变换、大小调整及类型转换等操作。常用函数如`cvtColor`可实现BGR到RGB、灰度图或HSV的转换;`resize`则用于调整图像分辨率。此外,通过`astype`或`convertScaleAbs`可改变图像数据类型。对于复杂的几何变换,如仿射或透视变换,则可利用`warpAffine`和`warpPerspective`函数实现。这些技术为图像处理提供了强大的工具。
WK
130 1
|
26天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
42 2
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
84 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
81 4
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
89 4
|
2月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
31 4