OpenCV4(C++)—— 图片的读取、(并排)显示与保存


前言

C++和python两者的使用语法都是相同的

一、读取(imread和imdecode)

1、imread

由两个参数决定:
imread(“图片的地址+名称”, 何种形式读取图片)

image = cv2.imread("C:/Opencv/lena.jpg", cv2.IMREAD_GRAYSCA)  // python
cv::Mat image = cv::imread("C:/Opencv/lena.jpg", 0); // c++

第二个参数,可以使用标志参数,也可以使用简记数字。常用的就是

     读取形式                            标志参数               简记数字
以原图读取(针对有Alpha通道的图片)      IMREAD_UNCHANGED           -1
以单通道的灰度图像读取                  IMREAD_GRAYSCA            0
以3通道BGR的彩色图片读取                 IMREAD_COLOR             1      

注意,缺省状态下是以3通道读取,并且是BGR的形式

2、imdecode

imread是从文件(磁盘)中直接读取图像数据,imdecode是从内存缓冲区中读取数据,并解码成图像格式

使用imdecode的优点在于可以从内存中直接解码图像数据,而不需要将数据保存到磁盘再进行读取。在某些场景中是有用的,如网络传输的数据源,摄像头捕获的图像数据。

imdecode与image的使用有一点要注意:imread是传入图片路径,转为图片格式;imdecode传入的内存数据(数组形式),转为图片格式。就以上面的简单例子:从文件中读取图片。imdecode的python写法可以为下:

# 使用 NumPy 的 fromfile 函数从指定路径中读取图像数据,并将其存储为 NumPy 数组,作为参数传给imdecode解码成图像格式
image = cv2.imdecode(np.fromfile("C:/Opencv/lena.jpg", dtype = np.uint8), 1)    # 1为标志参数,3通道读取

注:一般情况下,读取图像的像素数目小于2^30,这个要求在绝大多数图像处理领域都是不受影响的,但是对于超高分辨率图像的像素数目可能会超过这个阈值,可以通过修改系统变量中的OPENCV_IO_MAX_IMAGE_PIXELS参数调整能够读取的最大像素数目。

二、显示(imshow)

显示图片一般调试时使用,没有什么特别注意的(反正最终结果也要将其注释掉)。
常用三件套:1)显示图片窗口 2)窗口的持续时间或阻塞 3)销毁窗口

cv::imshow("Show", image); // "Show"是显示窗口的名称,image是读取的图片
//cv::waitKey(300) // 窗口持续300ms后关闭,继续后续程序
cv::waitKey(0);   // 0 将会一直阻塞程序的执行,直到用户按下键盘上的任意键
cv::destroyAllWindows();  // 关闭程序中所有的窗口,一般用于程序的最后

注:如果原图分辨率太大,显示不完全怎么办? 使用namedWindow()这个窗口函数设置一下。

此外,某些场景下想让图片并排表示,来更好的对比效果,可以使用以下方式(仅当展示图片的尺寸相同时):

    cv::Mat img = cv::imread("C:/Users/20231.jpg");
    cv::Mat img1 = cv::imread("C:/Users/3-353S02073-0_WA.jpg");
    cv::Mat img2 = cv::imread("C:/Users/301-4-353S02073-0_WA.jpg");

    // 获取每张图像的大小
    int h = img.rows;
    int w = img.cols;
    int h1 = img1.rows;
    int w1 = img1.cols;
    int h2 = img2.rows;
    int w2 = img2.cols;

    // 创建一个大画布用于展示三张图像
    cv::Mat canvas(std::max(h, std::max(h1, h2)), w + w1 + w2, CV_8UC3, cv::Scalar(0, 0, 0));

    // 将三张图像放置在合适的位置上
    img.copyTo(canvas(cv::Rect(0, 0, w, h)));
    img1.copyTo(canvas(cv::Rect(w, 0, w1, h1)));
    img2.copyTo(canvas(cv::Rect(w + w1, 0, w2, h2)));

    cv::imshow("Merged Images", canvas);
    cv::waitKey(0);
    cv::destroyAllWindows();

python代码如下:

img = cv2.imread("img.jpg")
img1 = cv2.imread("img1.jpg")
img2 = cv2.imread("img2.jpg")

# 获取每张图像的大小
h, w, _ = img.shape
h1, w1, _ = img1.shape
h2, w2, _ = img2.shape

# 创建一个大画布用于展示三张图像
canvas = np.zeros((max(h, h1, h2), w + w1 + w2, 3), dtype=np.uint8)

# 将三张图像放置在合适的位置上
canvas[:h, :w] = img
canvas[:h1, w:w+w1] = img1
canvas[:h2, w+w1:] = img2

# 显示合并后的图像
cv2.imshow("Merged Images", canvas)
cv2.waitKey(0)
cv2.destroyAllWindows()

三、保存(imwrite和imencode)

1、imwrite

与读取imread相似,要给出具体保存的路径(地址+图片名

    cv::Mat image = cv::imread("C:/Opencv/lena.jpg", cv::IMREAD_GRAYSCALE);
    cv::imwrite("C:/Opencv/temp/lena.jpg", image);

值得注意的是批量图片的保存。通常方法都是 :(固定的文件夹地址)+(流动的图片名)

( 注:imwrite函数还有第三个参数,用于保存不同格式的图像。如果保存的图像是单通道或三通道,那第三个参数可以忽略。但如果保存的是特殊格式(如16位深度图像),则需要设置第三个参数。(

2、imencode

imencode函数是将图像数据编码成流数据(如png格式,jpg格式),返回的是一个元组(bool,NumPy),第一个元素是布尔值,表示编码是否成功;第二个是编码后的数据——NumPy数组。若想把数据保存到文件中,还需要其他步骤,例如,python中使用.tofile(.tofile() 是 NumPy 数组的一个方法,用于将数组中的数据以二进制形式写入文件):

image = cv2.imdecode(np.fromfile("C:/Opencv/lena.jpg", dtype = np.uint8), -1)
cv2.imencode('.png', image)[1].tofile("C:/Opencv/temp/ena.png") // 索引[1]取出元组中的第二个元素,即编码后的图像数据

总结

imdecode和imencode是进行与内存缓冲区之间的操作(而不是磁盘),在某些场景下更加高效,但C++中使用这两个比较繁琐,python中使用较为方便。此外,当图片名字含有中文时,使用imwrite保存下来的图片名字可能会出现像“鍐风剨”这种乱码,而使用 imencode 可以避免这种情况。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想要躺平的一枚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值