OpenCV入门(C++/Python)-使用OpenCV裁剪图像(四)

简介: OpenCV入门(C++/Python)-使用OpenCV裁剪图像(四)

裁剪是为了从图像中删除所有不需要的物体或区域。甚至突出显示图像的特定功能。


使用OpenCV裁剪没有特定的功能,NumPy数组切片是工作。读取的每个图像都存储在2D数组中(对于每个颜色通道)。只需指定要裁剪区域的高度和宽度(以像素为单位),就可以完成


1.使用OpenCV裁剪


以下代码片段展示了如何使用Python和C++裁剪图像。在例子的进一步,您将详细了解这些。


Python


# Import packages
import cv2
import numpy as np
img = cv2.imread('test.jpg')
print(img.shape) # Print image shape
cv2.imshow("original", img)
# Cropping an image
cropped_image = img[400:1200, 350:700]
# Display cropped image
cv2.imshow("cropped", cropped_image)
# Save the cropped image
cv2.imwrite("Cropped Image.jpg", cropped_image)
cv2.waitKey(0)
cv2.destroyAllWindows()


C++


// Include Libraries
#include<opencv2/opencv.hpp>
#include<iostream>
// Namespace nullifies the use of cv::function();
using namespace std;
using namespace cv;
int main()
{
  // Read image
  Mat img = imread("test.jpg");
  cout << "Width : " << img.size().width << endl;
  cout << "Height: " << img.size().height << endl;
  cout<<"Channels: :"<< img.channels() << endl;
  // Crop image
  Mat cropped_image = img(Range(400,1200), Range(350,700));
  //display image
  imshow(" Original Image", img);
  imshow("Cropped Image", cropped_image);
  //Save the cropped Image
  imwrite("Cropped Image.jpg", cropped_image);
  // 0 means loop infinitely
  waitKey(0);
  destroyAllWindows();
  return 0;
}


上面的代码读取并显示图像及其尺寸。尺寸不仅包括二维矩阵的宽度和高度,还包括通道的数量(例如,RGB图像有3个通道——红色、绿色和蓝色)。

让我们尝试裁剪图像中包含美女的部分。


Python


cropped_image = img[400:1200, 350:700] # Slicing to crop the image
# Display the cropped image
cv2.imshow("cropped", cropped_image)
cv2.waitKey(0)
cv2.destroyAllWindows() 


C++


Mat crop = img(Range(400,1200),Range(350,700)); // Slicing to crop the image
// Display the cropped image
imshow("Cropped Image", crop);
waitKey(0);
destroyAllWindows();
return 0;


在Python中,您可以使用与NumPy数组切片相同的方法裁剪图像。要切片数组,您需要指定第一维和第二维的开始和结束索引。

  • 第一个维度总是行数或图像的高度。
  • 第二个维度是列数或图像的宽度。

如何剪切图像的NumPy数组?查看此示例中的语法:


cropped = img[start_row:end_row, start_col:end_col]


在C++中,我们使用Range()函数裁剪图像。

Python同理一样,它也应用切片。

在这里,图像也按照上述相同的约定作为二维矩阵读取。

以下是裁剪图像的C++语法:



img(Range(start_row, end_row), Range(start_col, end_col))
• 1


2.使用裁剪功能对图像进行划分


在OpenCV中裁剪的一个实际应用可以是将图像划分为大小相同图像块。使用循环从图像中裁剪片段。首先从图像的形状中获取所需图像块的高度和宽度


Python


img =  cv2.imread("test_cropped.jpg")
image_copy = img.copy() 
imgheight=img.shape[0]
imgwidth=img.shape[1]


C++


Mat img = imread("test_cropped.jpg");
Mat image_copy = img.clone();
int imgheight = img.rows;
int imgwidth = img.cols;


加载高度和宽度,以指定需要裁剪较小图像块的范围。为此,使用Python中的range()函数。现在,使用两个循环裁剪:


宽度范围

高度范围

已知原图像瘩高度宽度为(1350,1080),我们使用的图像块的高度和宽度分别为(270,216)。内外循环的步幅(我们在图像中移动的像素数)也就是划分下来,有25个图像块。(拼图一样)


Python


M = 216
N = 270
x1 = 0
y1 = 0
for y in range(0, imgheight, M):
    for x in range(0, imgwidth, N):
        if (imgheight - y) < M or (imgwidth - x) < N:
            break
        y1 = y + M
        x1 = x + N
        # check whether the patch width or height exceeds the image width or height
        if x1 >= imgwidth and y1 >= imgheight:
            x1 = imgwidth - 1
            y1 = imgheight - 1
            # Crop into patches of size MxN
            tiles = image_copy[y:y + M, x:x + N]
            # Save each patch into file directory
            cv2.imwrite(str(x) + '_' + str(y) + '.jpg', tiles)
            cv2.rectangle(img, (x, y), (x1, y1), (0, 255, 0), 1)
        elif y1 >= imgheight:  # when patch height exceeds the image height
            y1 = imgheight - 1
            # Crop into patches of size MxN
            tiles = image_copy[y:y + M, x:x + N]
            # Save each patch into file directory
            cv2.imwrite(str(x) + '_' + str(y) + '.jpg', tiles)
            cv2.rectangle(img, (x, y), (x1, y1), (0, 255, 0), 1)
        elif x1 >= imgwidth:  # when patch width exceeds the image width
            x1 = imgwidth - 1
            # Crop into patches of size MxN
            tiles = image_copy[y:y + M, x:x + N]
            # Save each patch into file directory
            cv2.imwrite(str(x) + '_' + str(y) + '.jpg', tiles)
            cv2.rectangle(img, (x, y), (x1, y1), (0, 255, 0), 1)
        else:
            # Crop into patches of size MxN
            tiles = image_copy[y:y + M, x:x + N]
            # Save each patch into file directory
            cv2.imwrite(str(x) + '_' + str(y) + '.jpg', tiles)
            cv2.rectangle(img, (x, y), (x1, y1), (0, 255, 0), 1)


C++


int M = 216;
int N = 270;
int x1 = 0;
int y1 = 0;
for (int y = 0; y<imgheight; y=y+M)
{
    for (int x = 0; x<imgwidth; x=x+N)
    {
        if ((imgheight - y) < M || (imgwidth - x) < N)
        {
            break;
        }
        y1 = y + M;
        x1 = x + N;
        string a = to_string(x);
        string b = to_string(y);
        if (x1 >= imgwidth && y1 >= imgheight)
        {
            x = imgwidth - 1;
            y = imgheight - 1;
            x1 = imgwidth - 1;
            y1 = imgheight - 1;
            // crop the patches of size MxN
            Mat tiles = image_copy(Range(y, imgheight), Range(x, imgwidth));
            //save each patches into file directory
            imwrite("saved_patches/tile" + a + '_' + b + ".jpg", tiles);  
            rectangle(img, Point(x,y), Point(x1,y1), Scalar(0,255,0), 1);    
        }
        else if (y1 >= imgheight)
        {
            y = imgheight - 1;
            y1 = imgheight - 1;
            // crop the patches of size MxN
            Mat tiles = image_copy(Range(y, imgheight), Range(x, x+N));
            //save each patches into file directory
            imwrite("saved_patches/tile" + a + '_' + b + ".jpg", tiles);  
            rectangle(img, Point(x,y), Point(x1,y1), Scalar(0,255,0), 1);    
        }
        else if (x1 >= imgwidth)
        {
            x = imgwidth - 1;   
            x1 = imgwidth - 1;
            // crop the patches of size MxN
            Mat tiles = image_copy(Range(y, y+M), Range(x, imgwidth));
            //save each patches into file directory
            imwrite("saved_patches/tile" + a + '_' + b + ".jpg", tiles);  
            rectangle(img, Point(x,y), Point(x1,y1), Scalar(0,255,0), 1);    
        }
        else
        {
            // crop the patches of size MxN
            Mat tiles = image_copy(Range(y, y+M), Range(x, x+N));
            //save each patches into file directory
            imwrite("saved_patches/tile" + a + '_' + b + ".jpg", tiles);  
            rectangle(img, Point(x,y), Point(x1,y1), Scalar(0,255,0), 1);    
        }
    }
}


接下来,使用imshow()函数显示图像块拼图。使用imwrite()函数将其保存到文件目录中。

Python


#Save full image into file directory
cv2.imshow("Patched Image",img)
cv2.imwrite("patched.jpg",img)
cv2.waitKey()
cv2.destroyAllWindows()


C++


imshow("Patched Image", img);
imwrite("patched.jpg",img);
waitKey();
destroyAllWindows();


Python

C++

相关文章
|
6月前
|
jenkins Shell 测试技术
|
6月前
|
安全 jenkins Java
Java、Python、C++支持jenkins和SonarQube(一)
Jenkins 是一个开源的 持续集成(CI)和持续交付(CD) 工具,用于自动化构建、测试和部署软件项目。它基于 Java 开发,支持跨平台运行,并拥有丰富的插件生态系统,可以灵活地扩展功能
424 5
|
6月前
|
jenkins Java Shell
Java、Python、C++支持jenkins和SonarQube(全集)
Jenkins 是一个开源的持续集成(CI)和持续交付(CD)工具,用于自动化构建、测试和部署软件项目。它基于 Java 开发,支持跨平台运行,并拥有丰富的插件生态系统,可以灵活地扩展功能
601 1
|
6月前
|
jenkins Java 持续交付
Java、Python、C++支持Jenkins和SonarQube(三)
Python与Jenkins和SonarQube
317 1
|
6月前
|
jenkins Java 测试技术
|
9月前
|
存储 安全 编译器
c++入门
c++作为面向对象的语言与c的简单区别:c语言作为面向过程的语言还是跟c++有很大的区别的,比如说一个简单的五子棋的实现对于c语言面向过程的设计思路是首先分析解决这个问题的步骤:(1)开始游戏(2)黑子先走(3)绘制画面(4)判断输赢(5)轮到白子(6)绘制画面(7)判断输赢(8)返回步骤(2) (9)输出最后结果。但对于c++就不一样了,在下五子棋的例子中,用面向对象的方法来解决的话,首先将整个五子棋游戏分为三个对象:(1)黑白双方,这两方的行为是一样的。(2)棋盘系统,负责绘制画面。
140 0
|
存储 分布式计算 编译器
C++入门基础2
本内容主要讲解C++中的引用、inline函数和nullptr。引用是变量的别名,与原变量共享内存,定义时需初始化且不可更改指向对象,适用于传参和返回值以提高效率;const引用可增强代码灵活性。Inline函数通过展开提高效率,但是否展开由编译器决定,不建议分离声明与定义。Nullptr用于指针赋空,取代C语言中的NULL。最后鼓励持续学习,精进技能,提升竞争力。
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
11月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
451 12