簡體   English   中英

想要對 Python 繪圖上的特定填充對象應用模糊

[英]Want to Apply Blur to a Specific Filled Object on Python Plot

我在 Linux Mint 20.3 Una 上使用 Python 3.8.10。 我正在制作一系列具有大量(可能數千個)魚形的動畫,每個魚形都是通過指定帶點的二維輪廓生成的,然后使用Pyplot 填充函數進行填充

我希望能夠做的是根據計算出的距離對這些單獨的填充區域中的每一個應用獨特的模糊以模擬圖像深度。

理論上,這可以通過導出 SVG 文件並在 Inkscape 或其他包中手動應用模糊來完成,但可能有成千上萬的魚和數百幀,因此在代碼中實現這一點的方法確實是唯一現實的方法如果可能的話,完成它。

這是生成我想模糊的單個填充配置文件的最小代碼:

import matplotlib.pyplot as plt
from scipy.ndimage import gaussian_filter

#define profile of object with points

x_profile = [0.5,0.485951301332915,0.423371700761206,0.358237605529776,0.281609306290982,0.23180095266422,0.152618567550257,0.053001860296735,-0.005746611462221,-0.060663545623872,-0.05683323438022,-0.257343937095579,-0.317369329156755,-0.345466399463283,-0.469348762061393,-0.492337251833031,-0.5,-0.439974607938825,-0.418263242861681,-0.415709156986512,-0.461686095651334,-0.492337415346851,-0.483397419850022,-0.466794594429313,-0.363346513092306,-0.342912313588113,-0.31864669912198,-0.289272544999412,-0.236909860226751,-0.210090037250083,-0.183269887245775,-0.146233189348514,-0.078544599457363,0.086206203027589,0.210088361233424,0.310982111424531,0.418261893872663,0.478287408569203,0.493612741389321]
y_profile = [-0.019156461632871,0.002554903444271,0.031928934931474,0.051085805348896,0.065134504015981,0.07024308455087,0.071518492350251,0.067688181106599,0.158365179012477,0.068965632828735,0.049808353626761,0.028096988549618,0.025542085105346,0.03192770857782,0.10217038434414,0.104725287788412,0.091954040843463,0.00255449465972,-0.00255449465972,-0.017879827479838,-0.067688181106599,-0.148148017942698,-0.158365179012477,-0.151979555540003,-0.061302557634125,-0.047254267751592,-0.040868235494567,-0.042143643293948,-0.080457792913345,-0.084288104156997,-0.079179523622108,-0.097059759886497,-0.111108049769031,-0.127710834311284,-0.126435426511903,-0.107278556094481,-0.076627072885143,-0.045975589675805,-0.031927299793271]

#make plot

fig = plt.figure(frameon=False)
fig.set_size_inches(6.5, 6.5)
ax = plt.axes()
ax.set_facecolor((0,0,1.0))
ax.set_xlim(-1,+1)
ax.set_ylim(-1,+1)
ax.set_aspect('equal', adjustable='box')
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)

#create filled region defined by profile points (I want to be able to apply a blur to this)
          
plt.fill(x_profile, y_profile, color = (0, 0, 0.5))

#tried the following, but does not work at all.

#handle = plt.fill(x_profile, y_profile, color = (0, 0, 0.5))
#blurred = gaussian_filter(handle, sigma=1)

#show plot (normally exporting PNG frames for animation)

plt.show()

這應該產生這個圖像:

魚的外形要模糊

如果這在 Python 中是不可能的,我願意接受關於如何以其他方式動態實現的建議。

我看過 SciPy 高斯模糊應用於靜態圖像區域的示例,但我想要實現的模糊特定於填充的“對象”,它不是一個整齊的矩形。 我注意到,當此圖像導出為 SVG 時,各個填充對象在該文件中顯示為不同的實體,但我沒有看到在 Python 中為其分配句柄並對其應用模糊的方法。 我試過 'handle = plt.fill(x,y)' 和 'gaussian_filter(handle, sigma=1)' 的變體,但沒有成功。

我想我能夠使用卷積來完成你所要求的,但它根本沒有針對速度進行優化。 另外,很難說它將如何轉化為更大的代碼。

從你發布的內容開始,我將圖表轉換為 rgb 數組,並使用從頭開始的卷積函數(不是我自己的1 )分別對每個維度進行卷積。 此代碼將輸出第一張魚圖像,幾秒鍾后將輸出模糊的魚圖像。

import matplotlib.pyplot as plt
import numpy as np
import cv2
import plotly.express as px

def Convolve(img, kernel):

    (imgX, imgY) = img.shape[:2]
    (kernelX, kernelY) = kernel.shape[:2]
    #print(imgX,imgY, kernelX,kernelY)
    pad = (kernelX - 1) // 2
    img = cv2.copyMakeBorder(img, pad, pad, pad, pad, cv2.BORDER_REPLICATE) #top, bottom, left, right
    #the above line prevents error with convolution: operands could not be broadcast together with shapes (23,22) (23,23)

    output = np.zeros((imgX, imgY), dtype="float32")

    #shift kernel vertical and horizontal across image, pad prevents kernel from going out of bounds
    for y in np.arange(pad, imgY + pad):
        for x in np.arange(pad, imgX + pad):
            #locate specific pixel
            roi = img[y - pad:y + pad + 1, x - pad:x + pad + 1]
            #print(roi)
            #perform convolution
            k = (roi * kernel).sum()
            #populate the result into the previously created np.zeroes array
            output[y - pad, x - pad] = k
    return output


# define profile of object with points

x_profile = [0.5, 0.485951301332915, 0.423371700761206, 0.358237605529776, 0.281609306290982, 0.23180095266422,
             0.152618567550257, 0.053001860296735, -0.005746611462221, -0.060663545623872, -0.05683323438022,
             -0.257343937095579, -0.317369329156755, -0.345466399463283, -0.469348762061393, -0.492337251833031, -0.5,
             -0.439974607938825, -0.418263242861681, -0.415709156986512, -0.461686095651334, -0.492337415346851,
             -0.483397419850022, -0.466794594429313, -0.363346513092306, -0.342912313588113, -0.31864669912198,
             -0.289272544999412, -0.236909860226751, -0.210090037250083, -0.183269887245775, -0.146233189348514,
             -0.078544599457363, 0.086206203027589, 0.210088361233424, 0.310982111424531, 0.418261893872663,
             0.478287408569203, 0.493612741389321]
y_profile = [-0.019156461632871, 0.002554903444271, 0.031928934931474, 0.051085805348896, 0.065134504015981,
             0.07024308455087, 0.071518492350251, 0.067688181106599, 0.158365179012477, 0.068965632828735,
             0.049808353626761, 0.028096988549618, 0.025542085105346, 0.03192770857782, 0.10217038434414,
             0.104725287788412, 0.091954040843463, 0.00255449465972, -0.00255449465972, -0.017879827479838,
             -0.067688181106599, -0.148148017942698, -0.158365179012477, -0.151979555540003, -0.061302557634125,
             -0.047254267751592, -0.040868235494567, -0.042143643293948, -0.080457792913345, -0.084288104156997,
             -0.079179523622108, -0.097059759886497, -0.111108049769031, -0.127710834311284, -0.126435426511903,
             -0.107278556094481, -0.076627072885143, -0.045975589675805, -0.031927299793271]

# make plot

fig = plt.figure(frameon=False)
fig.set_size_inches(6.5, 6.5)
ax = plt.axes()
ax.set_facecolor((0, 0, 1.0))
ax.set_xlim(-1, +1)
ax.set_ylim(-1, +1)
ax.set_aspect('equal', adjustable='box')
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)

# create filled region defined by profile points (I want to be able to apply a blur to this)

plt.fill(x_profile, y_profile, color=(0, 0, 0.5))
fig.canvas.draw()

data = np.frombuffer(fig.canvas.tostring_rgb(), dtype=np.uint8)
data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,))
array=np.array(data)
R=array[:,:,0]
G=array[:,:,1]
B=array[:,:,2]

fig=px.imshow(array, color_continuous_scale="gray")
fig.show()

_1DKern = cv2.getGaussianKernel(33, 2)  # first value is dimensions, second is sigma
_2DKern = np.outer(_1DKern, _1DKern.transpose())
convR = Convolve(R, _2DKern)
convG=Convolve(G,_2DKern)
convB=Convolve(B,_2DKern)
conv=np.stack([convR,convG,convB],2)

fig = px.imshow(conv, color_continuous_scale="gray")
fig.show()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM