Phần 5. Cắt, xóa trong ảnh với OpenCV

0
2939
cropping

Thao tác cắt được thực hiện để loại bỏ tất cả các đối tượng hoặc khu vực không mong muốn khỏi hình ảnh. Hoặc thậm chí để làm nổi bật một tính năng cụ thể của hình ảnh.

Không có hàm cụ thể nào để cắt ảnh trong OpenCV mà được thực hiện thông qua tính chất của mảng NumPy. Mọi hình ảnh được đọc vào sẽ được lưu trữ trong một mảng 2D (cho mỗi kênh màu). Sau đó chỉ định chiều cao và chiều rộng (tính bằng pixel) của khu vực sẽ được cắt.

Bài viết gồm các nội dung chính sau:

1. Cắt ảnh với OpenCV

2. Chia ảnh thành các phần nhỏ

3. Ứng dụng của việc cắt ảnh

Dưới đây là đoạn code mẫu dùng để cắt ảnh viết bằng C++ và Python

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[80:280, 150:330]

# 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(80,280), Range(150,330));

	//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;
}

1. Cắt ảnh với OpenCV

Hình ảnh dưới đây sẽ được sử dụng làm ảnh đầu vào cho cả bài viết

Python

img=cv2.imread('test.png')

# Prints Dimensions of the image
print(img.shape) 

# Display the image
cv2.imshow("original", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

C++

Mat img = imread("test.jpg");

//Print the height and width of the image
cout << "Width : " << img.size().width << endl;
cout << "Height: " << img.size().height << endl;
cout << "Channels: " << img.channels() << endl;

// Display image
imshow("Image", img);
waitKey(0);
destroyAllWindows();

Đoạn code trên đọc và hiển thị một hình ảnh và kích thước của nó. Kích thước không chỉ bao gồm chiều rộng và chiều cao của ma trận 2-D mà còn bao gồm cả số kênh (ví dụ: hình ảnh RGB có 3 kênh – Red, Green and Blue). Tiếp theo sẽ thử cắt một phần của hình ảnh có hoa.

Python

cropped_image = img[80:280, 150:330] # Slicing to crop the image

# Display the cropped image
cv2.imshow("cropped", cropped_image)
cv2.waitKey(0)
cv2.destroyAllWindows() 

C++

Mat crop = img(Range(80,280),Range(150,330)); // Slicing to crop the image

// Display the cropped image
imshow("Cropped Image", crop);

waitKey(0);
destroyAllWindows();
return 0;

Trong Python, việc cắt hình ảnh tương tự như cắt mảng NumPy. Để cắt một mảng, bạn cần chỉ định chỉ số bắt đầu và kết thúc của chiều cao và chiều rộng.

– Kích thước đầu tiên luôn là số hàng hoặc chiều cao của hình ảnh.

– Kích thước thứ hai là số cột hoặc chiều rộng của hình ảnh.

Với quy ước rằng kích thước đầu tiên của một mảng 2D là các hàng của mảng (trong đó mỗi hàng đại diện cho tọa độ y của hình ảnh). Cú pháp để cắt một mảng NumPy:

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

Trong C ++, hàm Range() được dùng để cắt hình ảnh. Cú pháp C ++ để cắt hình ảnh như sau:

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

2. Chia ảnh thành các phần nhỏ

Một ứng dụng thực tế của việc cắt trong OpenCV là có thể chia hình ảnh thành các mảng nhỏ hơn. Trước hết cần lấy ra thông tin về kích thước ảnh. Sau đó sử dụng các vòng lặp để cắt ra một phần từ hình ảnh.

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;

Sau đó sử dụng hàm range() và 2 vòng lặp for

– Một vòng lặp cho phạm vi chiều rộng

– Một vòng lặp cho phạm vi chiều cao

Python

M = 76
N = 104
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('saved_patches/'+'tile'+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('saved_patches/'+'tile'+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('saved_patches/'+'tile'+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('saved_patches/'+'tile'+str(x)+'_'+str(y)+'.jpg', tiles)
            cv2.rectangle(img, (x, y), (x1, y1), (0, 255, 0), 1)

C++

int M = 76;
int N = 104;

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);    
        }
    }
}

Các phần nhỏ cần được cắt trong đoạn code mẫu được chọn với chiều cao là 76 và chiều rộng là 104. Bước nhảy (số pixel di chuyển trong ảnh) được chọn bằng với kích thước của một phần nhỏ được cắt.

Tiếp theo sử dụng hàm imshow() để quan sát kết quả và hàm imwrite() để ghi lại kết quả.

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();

Ảnh GIF dưới đây minh họa quá trình thực thi code để chia hình ảnh thành các phần nhỏ.

Kết quả sau khi thực hiện chia thành các phần nhỏ sẽ như sau:

Hình ảnh dưới đây hiển thị các phẩn ảnh nhỏ riêng biệt được lưu vào thư mục

3. Ứng dụng của việc cắt ảnh

Bạn có thể sử dụng tính năng cắt để trích xuất một vùng quan tâm từ hình ảnh và loại bỏ các phần khác mà không cần sử dụng.

Bạn có thể trích xuất các phần từ một hình ảnh làm đầu vào cho mạng nơ-ron để thực hiện quá trình training.

Có thể sử dụng ứng dụng web Streamlit để thực hiện việc cắt ảnh theo các bước sau:

– Tải hình ảnh cần được cắt từ thư mục trên máy của người dùng.

– Sau đó, cắt hình ảnh bằng cách chỉ định kích thước của nó.

Ở bài viết tiếp theo, chúng ta sẽ cùng tìm hiểu cách xoay và dịch ảnh với OpenCV.

Biên dịch: Thảo Nguyễn

Để cập nhật tin tức công nghệ mới nhất và các sản phẩm của công ty AIoT JSC, vui lòng truy cập link: http://aiots.vn hoặc linhkienaiot.com

5 1 Bỏ phiếu
Article Rating
Subscribe
Notify of
guest
0 Comments
Phản hồi nội tuyến
Xem tất cả các bình luận