Xử lý ảnh - OpenCV resize, crop và padding hình ảnh (code Python và C++)

  Sep 26, 2018      2m
   

OpenCV - tut 2

Xử lý ảnh - OpenCV resize, crop và padding hình ảnh (code Python và C++)

Môi trường làm việc với OpenCV

  • Linux (bài viết sử dụng Ubuntu 16.04)
  • OpenCV (bài viết sử dụng OpenCV 3.4.1)
  • Python (bài viết sử dụng Python 3.5.5)
  • Ảnh mẫu để xử lý (bài viết sử dụng ảnh girl_xinh_2.jpg)

Quan trọng nhất vẫn là có ảnh mẫu để ta xử lý, hehe (keyword tìm kiếm cho ông nào cần ^^: girl xinh, cụ thể là tui lụm từ bài viết kenh14 :P):

Anh girl xinh 2 opencvgirl_xinh_2.jpg

Bạn có thể download ảnh mẫu về.

File hình ảnh và source code python ở cùng thư mục:

  • girl_xinh_2.jpg
  • resize.py <– file python ở cùng thư mục với ảnh cho dễ thao tác

Resize ảnh với OpenCV - Python

Resize, hay gọi cách khác là scale ảnh, là việc ta chỉnh kích thước ảnh về kích thước mới (có thể giữ tỉ lệ ảnh ban đầu hoặc không).

resize.py: đọc file ảnh lên, resize ảnh (thay đổi kích thước), lưu xuống với OpenCV:

import cv2

IMG_PATH = 'girl_xinh_2.jpg'

# read image
img = cv2.imread(IMG_PATH)
print(IMG_PATH, img.shape)

new_width = 800
new_height = 400
img_resized = cv2.resize(src=img, dsize=(new_width, new_height))
reisze_img_name = 'girl_xinh_2_%dx%d.jpg' % (new_width, new_height)
cv2.imwrite(reisze_img_name, img_resized)
print(reisze_img_name, img_resized.shape)

fx = 0.5
fy = 1.0
img_resized = cv2.resize(src=img, dsize=None, fx=fx, fy=fy)
reisze_img_name = 'girl_xinh_2_fx=%.1f_fy=%.1f.jpg' % (fx, fy)
cv2.imwrite(reisze_img_name, img_resized)
print(reisze_img_name, img_resized.shape)

print('Done')

Thực thi lệnh trên terminal để đọc ảnh:

$ python resize.py
girl_xinh_2.jpg (720, 960, 3)
girl_xinh_2_800x400.jpg (400, 800, 3)
girl_xinh_2_fx=0.5_fy=1.0.jpg (720, 480, 3)
Done

Script ghi ra 2 ảnh mới:

  • girl_xinh_2_800x400.jpg: giờ thì girl xinh của chúng ta đã bị kéo mặt mập ra rồi, heeh.
  • girl_xinh_2_fx=0.5_fy=1.0.jpg

Giải thích về các tham số resize biến đổi kích thước ảnh OpenCV Python:

  • Lệnh chỉnh kích thước: cv2.resize()
  • dsize: kích thước mới (width, height). Tuy tổ chức dữ liệu là Height Width Channel nhưng tham số truyền vào là tuple lại sắp xếp Width trước rồi Height sau. Các bạn chú ý điểm này.
  • fx, fy: dùng để biến đổi theo tỉ lệ ảnh thay vì kích thước tuyệt đối.

Các bạn có thể nghịch với đoạn code bằng cách chỉnh các tham số ^^.

Crop ảnh với OpenCV - Python

crop.py: đọc file ảnh lên, crop vùng ảnh theo trục y (50:400), theo trục x (240:720), lưu xuống với OpenCV:

import cv2

IMG_PATH = 'girl_xinh_2.jpg'

# read image
img = cv2.imread(IMG_PATH)
print(IMG_PATH, img.shape)

img_crop = img[50:400, 240:720, :]
crop_name = 'girl_xinh_2_crop.jpg'
print(crop_name, img_crop.shape)

cv2.imwrite(crop_name, img_crop)
print('Done')

Từ giờ về sau mình sẽ không nhắc đến câu lệnh thực thi code python OpenCV nữa, cú pháp mặc định như mọi lần nhe $ python tên_file.py:

$ python crop.py
girl_xinh_2.jpg (720, 960, 3)
girl_xinh_2_crop.jpg (350, 480, 3)
Done

Sau khi cắt ảnh ra, ta chỉ còn mặt của cô gái. Mà không sao, em ấy vẫn xinh, kaka. :D.

girl_xinh_2_crop.jpg

girl_xinh_2_crop.jpg

Padding ảnh với OpenCV - Python

Padding ảnh là gì?

Padding ảnh là việc mà mình thêm các pixel vào các cạnh của ảnh để mở rộng ảnh ra.

Padding ảnh:

  • Thông thường giá trị pixel padding thêm sẽ là zero. Tức có màu đen.
  • Padding sẽ cho hiệu ứng zoom out. Tức nội dung ảnh sẽ nhỏ đi so với toàn ảnh.
  • Bạn có thể tạo hiệu ứng grid bằng cách:
    • Dùng OpenCV padding 1 ảnh to ra 2 lần về bên phải và xuống dưới.
    • Sau đó đọc nội dung 3 ảnh khác bằng OpenCV rồi cắt dán các pixel vào 3 vùng trống vừa mở rộng ra bằng padding.
    • Kết quả cuối cùng cho ảnh grid 2x2.

Nào, ta cùng padding ảnh thôi!

padding.py: padding ảnh thành kích thước 1000x1000

import cv2
import numpy as np

IMG_PATH = 'girl_xinh_2.jpg'

# read image
img = cv2.imread(IMG_PATH)
print(IMG_PATH, img.shape)  # (720, 960, 3)

img_pad = np.zeros([1000, 1000, 3])
img_pad += 100      # grey color BGR: [100, 100, 100] <=> hex: #646464
img_pad[140:860, 20:980,:] = img

cv2.imwrite('girl_xinh_2_pad.jpg', img_pad)
print('girl_xinh_2_pad.jpg:', img_pad.shape)
print('Done')

image padding

Resize ảnh với OpenCV - C++

resize.cpp

#include <iostream>
using namespace std;

#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>     // Basic OpenCV structures (cv::Mat)
// using namespace cv;

int main() {
    cv::Mat img = cv::imread("girl_xinh_2.jpg", cv::IMREAD_COLOR);  // (720, 960, 3)
    cv::Mat img_resize;
    cv::resize(img, img_resize, cv::Size(800,400));
    cv::imwrite("girl_xinh_800x400.jpg", img_resize);
}

Crop ảnh với OpenCV - C++

crop.cpp

#include <iostream>
using namespace std;

#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>     // Basic OpenCV structures (cv::Mat)
// using namespace cv;

int main() {
    cv::Mat img = cv::imread("girl_xinh_2.jpg", cv::IMREAD_COLOR);  // (720, 960, 3)
    
    int startX=240, startY=50, width=480, height=350;
    cv::Mat ROI(img, cv::Rect(startX, startY, width, height));

    cv::Mat croppedImage;
    // Copy the data into new matrix
    ROI.copyTo(croppedImage);

    cv::imwrite("girl_xinh_2_crop.jpg", croppedImage);
}

Padding ảnh với OpenCV - C++

padding.cpp

#include <iostream>
using namespace std;

#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>     // Basic OpenCV structures (cv::Mat)
// using namespace cv;

int main() {
    cv::Mat img = cv::imread("girl_xinh_2.jpg", cv::IMREAD_COLOR);  // (720, 960, 3)
        
    int new_height = 1000;
    int new_width = 1000;
    cv::Mat img_pad(new_height, new_width, img.type());
    img_pad.setTo(100);
    
    int x = 20;
    int y = 140;
    int width = 980 - x;
    int height = 860 - y;
    img.copyTo(img_pad(cv::Rect(x, y, width, height)));
    
    cv::imwrite("girl_xinh_2_pad.jpg", img_pad);
}

Sẽ có series các bài tiếp theo về dùng thư viện OpenCV trong xử lý ảnh, các bạn nhớ like trang Facebook để đón xem thông báo bài viết mới nhé! : https://www.facebook.com/minhng.info

Danh sách bài viết series OpenCV: