Sự biến dạng chụm / phồng bằng Python OpenCV

Sep 26 2020

Tôi muốn áp dụng bộ lọc chụm / phồng trên hình ảnh bằng Python OpenCV. Kết quả sẽ là một số loại ví dụ sau:

https://pixijs.io/pixi-filters/tools/screenshots/dist/bulge-pinch.gif

Tôi đã đọc bài đăng stackoverflow sau đây sẽ là công thức chính xác cho bộ lọc: Công thức cho biến dạng Thùng / Pincushion

Nhưng tôi đang đấu tranh để triển khai điều này trong Python OpenCV.

Tôi đã đọc về bản đồ để áp dụng bộ lọc trên hình ảnh: Làm biến dạng ect bằng OpenCv-python

Theo hiểu biết của tôi, mã có thể trông giống như sau:

import numpy as np
import cv2 as cv

f_img = 'example.jpg'
im_cv = cv.imread(f_img)

# grab the dimensions of the image
(h, w, _) = im_cv.shape

# set up the x and y maps as float32
flex_x = np.zeros((h, w), np.float32)
flex_y = np.zeros((h, w), np.float32)

# create map with the barrel pincushion distortion formula
for y in range(h):
    for x in range(w):
        flex_x[y, x] = APPLY FORMULA TO X
        flex_y[y, x] = APPLY FORMULA TO Y

# do the remap  this is where the magic happens
dst = cv.remap(im_cv, flex_x, flex_y, cv.INTER_LINEAR)

cv.imshow('src', im_cv)
cv.imshow('dst', dst)

cv.waitKey(0)
cv.destroyAllWindows()

Đây có phải là cách chính xác để đạt được độ méo được trình bày trong hình ảnh ví dụ không? Bất kỳ trợ giúp nào liên quan đến các nguồn thông tin hữu ích hoặc các ví dụ tốt nhất đều được đánh giá cao.

Trả lời

4 fmw42 Sep 26 2020 at 01:46

Bạn có thể làm điều đó bằng cách sử dụng các tùy chọn phát nổ và phát nổ trong Python Wand, sử dụng ImageMagick.

Đầu vào:

from wand.image import Image
import numpy as np
import cv2

with Image(filename='zelda1.jpg') as img:
    img.virtual_pixel = 'black'
    img.implode(0.5)
    img.save(filename='zelda1_implode.jpg')
    # convert to opencv/numpy array format
    img_implode_opencv = np.array(img)
    img_implode_opencv = cv2.cvtColor(img_implode_opencv, cv2.COLOR_RGB2BGR)

with Image(filename='zelda1.jpg') as img:
    img.virtual_pixel = 'black'
    img.implode(-0.5 )
    img.save(filename='zelda1_explode.jpg')
    # convert to opencv/numpy array format
    img_explode_opencv = np.array(img)
    img_explode_opencv = cv2.cvtColor(img_explode_opencv, cv2.COLOR_RGB2BGR)

# display result with opencv
cv2.imshow("IMPLODE", img_implode_opencv)
cv2.imshow("EXPLODE", img_explode_opencv)
cv2.waitKey(0)

Mã hóa:

Phát nổ:

3 DaviJones Sep 27 2020 at 15:11

Sau khi tự làm quen với mã nguồn ImageMagick, tôi đã tìm ra cách áp dụng công thức cho sự biến dạng. Với sự trợ giúp của chức năng bản đồ lại OpenCV , đây là một cách để làm sai lệch hình ảnh:

import numpy as np
import cv2 as cv

f_img = 'example.jpg'
im_cv = cv.imread(f_img)

# grab the dimensions of the image
(h, w, _) = im_cv.shape

# set up the x and y maps as float32
flex_x = np.zeros((h, w), np.float32)
flex_y = np.zeros((h, w), np.float32)

# create map with the barrel pincushion distortion formula
for y in range(h):
    delta_y = scale_y * (y - center_y)
    for x in range(w):
        # determine if pixel is within an ellipse
        delta_x = scale_x * (x - center_x)
        distance = delta_x * delta_x + delta_y * delta_y
        if distance >= (radius * radius):
            flex_x[y, x] = x
            flex_y[y, x] = y
        else:
            factor = 1.0
            if distance > 0.0:
                factor = math.pow(math.sin(math.pi * math.sqrt(distance) / radius / 2), -amount)
            flex_x[y, x] = factor * delta_x / scale_x + center_x
            flex_y[y, x] = factor * delta_y / scale_y + center_y

# do the remap  this is where the magic happens
dst = cv.remap(im_cv, flex_x, flex_y, cv.INTER_LINEAR)

cv.imshow('src', im_cv)
cv.imshow('dst', dst)

cv.waitKey(0)
cv.destroyAllWindows()

Điều này có tác dụng tương tự như sử dụng hàm chuyển đổi -implode từ ImageMagick.