图像的基础操作
当前系列所有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 |
我们测试用的图片如下:

demo1:使所有像素的红色通道值都为 0

demo2:输出图像的长宽以及通道数

demo3:边界扩张与虚化

C#版本运行效果及代码如下:
C#版本目前只整理了3组demo,其中,像素点修改和ROI提取,与python版本格式相差较大,我这边就不做演示了。
using OpenCvSharp;
namespace demo
{
internal class Program
{
public static void Main(string[] args)
{
demo1();
demo2();
demo3();
}
// 使所有像素的红色通道值都为 0
public static void demo1()
{
Mat img = Cv2.ImRead("../../../images/messi5.jpg");
Mat[] mv;
Cv2.Split(img, out mv); // 比较耗时的操作
Cv2.Merge(mv, img);
// 获取三通道颜色
Mat b = mv[0];
Mat g = mv[1];
Mat r = mv[2];
//使所有像素的红色通道值都为 0,你不必先拆分再赋值。
mv[0] = new Mat(mv[0].Size(), mv[0].Type(), new Scalar(0));
Cv2.Merge(mv, img);
Cv2.ImShow("DEMO1", img);
Cv2.WaitKey(0);
}
// 输出图像的长宽以及通道数
public static void demo2()
{
Mat img = Cv2.ImRead("../../../images/messi5.jpg");
System.Console.WriteLine($"行/高:{img.Rows}");
System.Console.WriteLine($"列/宽:{img.Cols}");
System.Console.WriteLine($"通道:{img.Channels()}");
System.Console.Read();
}
// 边界扩张与虚化
public static void demo3()
{
Mat replicate = new Mat();
Mat reflect = new Mat();
Mat reflect101 = new Mat();
Mat wrap = new Mat();
Mat constant = new Mat();
Mat img = Cv2.ImRead("../../../images/messi5.jpg");
Cv2.CopyMakeBorder(img, replicate, 50, 50, 50, 50, BorderTypes.Replicate);
Cv2.CopyMakeBorder(img, reflect, 50, 50, 50, 50, BorderTypes.Reflect);
Cv2.CopyMakeBorder(img, reflect101, 50, 50, 50, 50, BorderTypes.Reflect101);
Cv2.CopyMakeBorder(img, wrap, 50, 50, 50, 50, BorderTypes.Wrap);
Cv2.CopyMakeBorder(img, constant, 50, 50, 50, 50, BorderTypes.Constant, new Scalar(255, 0, 0)); // 边界颜色
Cv2.ImShow("replicate", replicate);
Cv2.ImShow("reflect", reflect);
Cv2.ImShow("reflect101", reflect101);
Cv2.ImShow("wrap", wrap);
Cv2.ImShow("constant", constant);
Cv2.WaitKey(0);
}
}
}
C++版本运行效果及代码如下:
C++版本目前只整理了3组demo,其中,像素点修改和ROI提取,与python版本格式相差较大,我这边就不做演示了。
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
// 使所有像素的红色通道值都为 0
void demo1()
{
Mat img = imread("../images/messi5.jpg");
Mat mv[3];
split(img, mv); // 比较耗时的操作
merge(mv, 3, img);
// 获取三通道颜色
Mat b = mv[0];
Mat g = mv[1];
Mat r = mv[2];
//使所有像素的红色通道值都为 0,你不必先拆分再赋值。
mv[0] = Scalar::all(0);
merge(mv, 3, img);
imshow("DEMO1", img);
}
// 输出图像的长宽以及通道数
void demo2()
{
Mat img = imread("../images/messi5.jpg");
cout << "行/高:" << img.rows << endl;
cout << "列/宽:" << img.cols << endl;
cout << "通道:" << img.channels() << endl;
}
// 边界扩张与虚化
void demo3()
{
Mat replicate;
Mat reflect;
Mat reflect101;
Mat wrap;
Mat constant;
Mat img = imread("../images/messi5.jpg");
copyMakeBorder(img, replicate, 50, 50, 50, 50, BORDER_REPLICATE);
copyMakeBorder(img, reflect, 50, 50, 50, 50, BORDER_REFLECT);
copyMakeBorder(img, reflect101, 50, 50, 50, 50, BORDER_REFLECT_101);
copyMakeBorder(img, wrap, 50, 50, 50, 50, BORDER_WRAP);
copyMakeBorder(img, constant, 50, 50, 50, 50, BORDER_CONSTANT, Scalar(255, 0, 0)); // 边界颜色
imshow("replicate", replicate);
imshow("reflect", reflect);
imshow("reflect101", reflect101);
imshow("wrap", wrap);
imshow("constant", constant);
}
int main()
{
demo1();
demo2();
demo3();
waitKey(0);
return 0;
}
Python版本运行效果及代码如下:
demo1:使所有像素的红色通道值都为 0
import cv2
img = cv2.imread('../images/messi5.jpg')
b, g, r = cv2.split(img) # 比较耗时的操作,请使用numpy 索引
img = cv2.merge((b, g, r))
# 获取三通道颜色
b = img[:, :, 0]
g = img[:, :, 1]
r = img[:, :, 2]
# 使所有像素的红色通道值都为 0,你不必先拆分再赋值。
# 你可以 直接使用 Numpy 索引,这会更快。
img[:, :, 0] = 0
# 保存到文件,看下效果
cv2.imshow('PythonApplication1.jpg', img)
cv2.waitKey(0)
demo2:输出图像的长宽以及通道数
import cv2
img = cv2.imread('../images/messi5.jpg', 0) # gray
print(img.shape)
img = cv2.imread('../images/messi5.jpg')
# print(img.shape)
rows, cols, ch = img.shape
print('行/高:', rows, '列/宽:', cols, '通道:', ch)
print(img.size)
print(img.dtype) # uint8
# 注意 在debug 时 img.dtype非常重要。因为在 OpenCV- Python 代码中经常出现数据类型的不一致。
demo3:plt.subplot的使用以及边界扩张
# -*- coding: utf-8 -*-
import cv2
import numpy as np
from matplotlib import pyplot as plt
# 为图像扩边,填充
#如果你想在图像周围创建一个边框,就像相框一样
# 经常在卷积运算或 0 填充时被用到。
BLUE = [255, 0, 0]
img1 = cv2.imread('opencv_logo.png')
replicate = cv2.copyMakeBorder(img1, top=10, bottom=10, left=10, right=10, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img1, 10, 10, 10, 10, cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img1, 10, 10, 10, 10, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img1, 10, 10, 10, 10, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img1, 50, 50, 50, 50, cv2.BORDER_CONSTANT, value=BLUE) # value 边界颜色
plt.subplot(231), plt.imshow(img1, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')
plt.show()
demo4:修改某个像素点的值:

# -*- coding: utf-8 -*-
import cv2
import numpy as np
img = cv2.imread('messi5.jpg')
#
px = img[100, 100]
print(px)
blue = img[100, 100, 0]
print(blue)
#
img[100, 100] = [255, 255, 255]
print(img[100, 100])
# 获取像素值及修改的更好方法。
print(img.item(10, 10, 2))
img.itemset((10, 10, 2), 100)
print(img.item(10, 10, 2))
demo5:ROI区域提取,并替换到新的坐标区域:
我们可以看到足球多了一个。。。

# -*- coding: utf-8 -*-
import cv2
import numpy as np
'''
例如我们 检测一副图像中 眼睛的位置 我们 先应该在图像中找到脸 再在脸的区域中找眼睛
而不是 直接在一幅图像中搜索。这样会提高程序的准确性和性能。
'''
img=cv2.imread('messi5.jpg')
ball=img[280:280+60,330:330+60] # 获取ROI区域
img[273:273+60,100:100+60]=ball # 将获取到的ROI区域替换到新的位置
# cv2.namedWindow("messi",0)
cv2.imshow("messi",img)
cv2.waitKey(0)