颜色空间转换与物体追踪
本章节内容是博主网上收集的。当前系列所有demo下载地址:
https://github.com/GaoRenBao/OpenCv4-Demo
不同编程语言对应的OpenCv版本以及开发环境信息如下:
语言 | OpenCv版本 | IDE |
C# | OpenCvSharp4.4.8.0.20230708 | Visual Studio 2022 |
C++ | OpenCv-4.5.5-vc14_vc15 | Visual Studio 2022 |
Python | OpenCv-Python (4.6.0.66) | PyCharm Community Edition 2022.1.3 |
在 OpenCV 中有超过150 种进行颜色空间转换的方法。具体包含那些,同学们可以在C++或者C#工程下,通过F12跳转到定义,查看所有的方法。
但是你以后就会发现我们经常用到的也就两种 BGR↔Gray 和 BGR↔HSV。
我们用到的函数是
cv2.cvtColor(input_image flag)
其中 flag 就是转换类型。
对于 BGR↔Gray 的转换,我们使用的 flag 就是 cv2.COLOR_BGR2GRAY。
同样对于 BGR↔HSV 的转换,我们用的 flag 就是 cv2.COLOR_BGR2HSV
C#版本运行效果及代码如下:
以下代码利用“BGR2HSV”色彩空间转换实现指定颜色识别,最终实现指定颜色的物体追踪。最终效果可以参考python版本的,效果是一样的:
using OpenCvSharp;
using System;
namespace ConsoleApp
{
internal class Program
{
static void Main(string[] args)
{
VideoCapture Cap = new VideoCapture();
// 打开ID为0的摄像头
Cap.Open(0);
// 判断摄像头是否成功打开
if (!Cap.IsOpened())
{
Console.WriteLine("摄像头打开失败.");
Console.Read();
return;
}
// 摄像头图像
Mat frame = new Mat();
// 设置蓝色的阈值
Scalar lower = new Scalar(90, 50, 50);
Scalar upper = new Scalar(130, 255, 255);
while (true)
{
if (Cap.Read(frame))
{
Mat hsv = new Mat();
Mat res = new Mat();
Mat mask = new Mat();
// 换到 HSV
Cv2.CvtColor(frame, hsv, ColorConversionCodes.BGR2HSV);
// 根据阈值构建掩模
Cv2.InRange(hsv, lower, upper, mask);
// 对原图像和掩模位运算
Cv2.BitwiseAnd(frame, frame, res, mask);
// 显示图像
Cv2.ImShow("frame", frame);
Cv2.MoveWindow("frame", 0, 0); // 原地
Cv2.ImShow("mask", mask);
Cv2.MoveWindow("mask", frame.Width, 0);// 右边
Cv2.ImShow("res", res);
Cv2.MoveWindow("res", 0, frame.Height);// 下边
Cv2.WaitKey(10);
}
}
}
}
}
C++版本运行效果及代码如下:
以下代码利用“BGR2HSV”色彩空间转换实现指定颜色识别,最终实现指定颜色的物体追踪。最终效果可以参考python版本的,效果是一样的:
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
void main()
{
VideoCapture Cap;
// 打开ID为0的摄像头
Cap.open(0);
// 判断摄像头是否成功打开
if (!Cap.isOpened())
{
cout << "摄像头打开失败" << endl;
return;
}
// 摄像头图像
Mat frame;
// 设置蓝色的阈值
Scalar lower = Scalar(90, 50, 50);
Scalar upper = Scalar(130, 255, 255);
while (true)
{
Cap >> frame;
if (!frame.empty())
{
Mat hsv, res, mask;
// 换到 HSV
cvtColor(frame, hsv, COLOR_BGR2HSV);
// 根据阈值构建掩模
inRange(hsv, lower, upper, mask);
// 对原图像和掩模位运算
bitwise_and(frame, frame, res, mask);
// 显示图像
imshow("frame", frame);
moveWindow("frame", 0, 0); // 原地
imshow("mask", mask);
moveWindow("mask", frame.cols, 0);// 右边
imshow("res", res);
moveWindow("res", 0, frame.rows);// 下边
waitKey(10);
}
}
}
Python版本运行效果及代码如下:
demo1:最基本的颜色空间转换示例
demo2:利用颜色识别实现物体追踪
demo1运行效果如下:

demo2代码则利用“COLOR_BGR2HSV”色彩空间转换实现指定颜色识别,最终实现指定颜色的物体追踪。实现效果如下:

import cv2
import numpy as np
'''
# 最基本的颜色空间转换示例
'''
def demo1():
# wrong
# green=np.uint8([0,255,0])
# print green
# hsv_green=cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
# print hsv_green
# scn (the number of channels of the source),
# i.e. self.img.channels(), is neither 3 nor 4.
#
# depth (of the source),
# i.e. self.img.depth(), is neither CV_8U nor CV_32F.
# 所以不能用 [0,255,0] 而 用 [[[0,255,0]]]
# 的三层括号应 分别对应于 cvArray cvMat IplImage
green = np.uint8([[[0, 255, 0]]])
hsv_green = cv2.cvtColor(green, cv2.COLOR_BGR2HSV)
print(hsv_green)
# [[[60 255 255]]]
black = np.uint8([[[0, 0, 0]]])
hsv_black = cv2.cvtColor(black, cv2.COLOR_BGR2HSV)
print(hsv_black)
# [[[0 0 0]]]
def demo2():
'''
物体跟踪
• 从视频中获取每一帧图像
• 将图像转换到 HSV 空间
• 设置 HSV 阈值到蓝色范围。
• 获取蓝色物体 当然我们 可以做其他任何我们想做的事
比如 在蓝色 物体周围画一个圈。
当你学习了【轮廓】之后 你就会学到更多 相关知识
那是你就可以找到物体的重心 并根据重心来跟踪物体
仅仅在摄像头前挥挥手就可以画出同的图形,或者其他更有趣的事。
'''
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
# ret = cap.set(3, 640)
# ret = cap.set(4, 480)
# 定蓝色的阈值
lower = np.array([90, 50, 50])
upper = np.array([130, 255, 255])
# 黄色-乒乓球
# lower = np.array([20, 100, 100])
# upper = np.array([30, 255, 255])
# 黑色
# lower = np.array([0, 0, 0])
# upper = np.array([180, 255, 30])
while True:
# 获取每一帧
ret, frame = cap.read()
# 换到 HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# 根据阈值构建掩模
mask = cv2.inRange(hsv, lower, upper)
# mask = cv2.inRange(hsv, lower_black, upper_black)
# 对原图像和掩模位运算
res = cv2.bitwise_and(frame, frame, mask=mask)
# 显示图像
cv2.imshow('frame', frame)
cv2.moveWindow('frame', x=0, y=0) # 原地
cv2.imshow('mask', mask)
cv2.moveWindow('mask', x=frame.shape[1], y=0) # 右边
cv2.imshow('res', res)
cv2.moveWindow('res', y=frame.shape[0], x=0) # 下边
k = cv2.waitKey(1) # & 0xFF
if k == ord('q'):
break
# 关闭窗口
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
demo1()
# demo2()