OpenCVのinpaint関数をGIMPから(Python経由で)使えるようにしてみました。
処理結果はこちらのサンプルみたいな感じ。
あまり大げさなことは出来ませんが、小さいノイズを消したりするのに便利なので、個人的に手放せません。
以下コード
関連
オマケ
- 知って得する5つの『GIMP』トリック
「四角選択ー>角丸」 一週間早く知りたかったー
わかってる不具合
なんでこうなるの?
- フィルタ動作後、レイヤーが非表示になったままです。
表示してやると、処理が画面に反映されます - アンドゥーがききません。
下記のプログラムが動くまでの道のり
- GIMP (レタッチソフト)
GIMP2を使おう - Python
GIMP2.4 win32版のプラグインをPythonで書く インストール編 - OpenCV
- CVtypes PythonからOpenCVを使うためのライブラリ
今回はパッチなしで動くようにしてみました。
「CVtypes.py」OpenCVをctypes経由で使う
その他のメモ
cvSetDataなどを使い、以前よりも、ちょっとだけ、GIMPとOpenCVの間の画像データのやりとりが速くなったはず。
#!/usr/bin/env python
from gimpfu import *
import CVtypes as cv
import ctypes
import sys
gettext.install("gimp20-python", gimp.locale_directory, unicode=True)
def cvImageAsString(img):
btype = ctypes.c_char * img[0].imageSize
return btype.from_address(img[0].imageData)
_cvDLL = ctypes.cdll.cv100
cvInpaint =cv.cfunc('cvInpaint',_cvDLL, None,
('src', ctypes.c_void_p, 1), # const CvArr* src
('mask', ctypes.c_void_p, 1), # CvArr* dst
('dst', ctypes.c_void_p, 1), # CvArr* dst
('flags', ctypes.c_int, 1), # int flags
('inpaintRadius', ctypes.c_double, 1), # double threshold1
)
def cvinpaint(img,layer):
r=10
gimp.progress_init("cvInPaint")
gimp.progress_update(0.5) #percnt 0 ->1.0
flag,x0,y0,x1,y1=gimp.pdb.gimp_selection_bounds(img)
ox,oy=layer.offsets
x0-=ox; x1-=ox; y0-=oy; y1-=oy
if not flag : return
x0=max(x0-r,0)
y0=max(y0-r,0)
x1=min(x1+r,layer.width)
y1=min(y1+r,layer.height)
r=float(r)
w=x1-x0; h=y1-y0
p0=layer.get_pixel_rgn(x0,y0,w,h)
src_img = cv.cvCreateImage( cv.CvSize( w,h), 8, p0.bpp )
cv.cvSetData(src_img,str(p0[:,:]),w*p0.bpp)
#---------------
stp=src_img[0].widthStep
sstr=cvImageAsString(src_img)
stp2=w*p0.bpp
idx0=0
for y in xrange(y0,y1):
idx1=idx0+stp2
p0[x0:x1,y]=sstr[idx0:idx1]
idx0+=stp
#---------------
if layer.bpp==4 :
src4=src_img
src_img=cv.cvCreateImage( cv.CvSize( w,h), 8, 3)
cv.cvCvtColor( src4, src_img,cv.CV_BGRA2BGR )
gimp.progress_update(0.6) #percnt 0 ->1.0
layer.visible=False
sel=img.selection
ps=sel.get_pixel_rgn(x0+ox,y0+oy,w,h)
mask_img = cv.cvCreateImage( cv.CvSize( w,h), 8, 1)
cv.cvSetData(mask_img,str(ps[:,:]),w)
dst_img = cv.cvCloneImage (src_img)
gimp.progress_update(0.7) #percnt 0 ->1.0
cvInpaint (src_img, mask_img, dst_img, cv.CV_INPAINT_TELEA, r)
gimp.progress_update(0.8) #percnt 0 ->1.0
if p0.bpp==4 :
cv.cvCvtColor( dst_img, src4, cv.CV_BGR2BGRA )
cv.cvReleaseImage(dst_img)
cv.cvOrS(src4, cv.CvScalar(0,0,0,255.0), src4)
dst_img=src4
dstr=cvImageAsString(dst_img)
stp=dst_img[0].widthStep
stp2=w*p0.bpp
idx0=0
for y in xrange(y0,y1):
idx1=idx0+stp2
p0[x0:x1,y]=dstr[idx0:idx1]
idx0+=stp
cv.cvRelease(dst_img)
cv.cvRelease(mask_img)
cv.cvRelease(src_img)
layer.visible=True
gimp.displays_flush()
gimp.progress_update(1.0)
#img.undo_group_end()
register(
"python-fu-cvinpaint",
N_("CvInPaint OpenCV"),
"Adds a layer of fog to the image.",
"BoxHeadRoom",
"BoxHeadroom.com",
"2007",
N_("_CvInPaint..."),
"RGB*, GRAY*",
[
(PF_IMAGE, "image", "Input image", None),
(PF_DRAWABLE, "drawable", "Input drawable", None),
],
[],
cvinpaint,
menu="<Image>/Filters/OpenCV",
domain=("gimp20-python", gimp.locale_directory)
)
main()
Tags: GIMP, OpenCV, Python