質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

2355閲覧

python opencv 画像切り抜き

退会済みユーザー

退会済みユーザー

総合スコア0

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2019/08/06 13:19

前提・実現したいこと

白地に描いた絵の一番外側の線(絵と白地の境界部分)で絵を切り抜き、その周りに透過処理を施した画像を作成したいです。

発生している問題・エラーメッセージ

切り抜くこと自体はできるのですが、マスク画像が意図しない形で生成されてしまい、変な風に切り抜いてしまいます。
イメージ説明
↑元画像
イメージ説明
↑マスク画像
イメージ説明
↑切り抜き後の画像

ソースコード

main.py

# -*- coding: utf-8 -*- from random import random from kivy.app import App from kivy.config import Config import clip import cv2 import os # 起動時の解像度の設定 Config.set('graphics', 'width', '1024') Config.set('graphics', 'height', '768') # 16:9 Config.set('graphics', 'resizable', False) # ウインドウリサイズ禁止 from kivy.uix.widget import Widget from kivy.uix.button import Button from kivy.graphics import Color, Ellipse, Line from kivy.properties import ObjectProperty from kivy.uix.behaviors import ToggleButtonBehavior from kivy.uix.togglebutton import ToggleButton from kivy.utils import get_color_from_hex # 色の16進数表示を可能にする from kivy.core.window import Window class MyPaintWidget(Widget): #pass last_color = '' # 画面クリアを押された場合の最後の色 line_width = 3 # 線の太さ def on_touch_down(self, touch): if Widget.on_touch_down(self, touch): return color = (random(), 1, 1) with self.canvas: touch.ud['line'] = Line(points=(touch.x, touch.y), width=self.line_width) def set_line_width(self, line_width=3): self.line_width = line_width def on_touch_move(self, touch): if touch.ud: # スライダーを動かす際のエラーを解除するため touch.ud['line'].points += [touch.x, touch.y] def set_color(self, new_color): self.last_color = new_color self.canvas.add(Color(*new_color)) class MyCanvasWidget(Widget): def clear_canvas(self): MyPaintWidget.clear_canvas(self) class MyPaintApp(App): def __init__(self, **kwargs): super(MyPaintApp, self).__init__(**kwargs) self.title = '画像表示' def build(self): parent = Widget() self.painter = MyCanvasWidget() # 起動時の色の設定を行う self.painter.ids['paint_area'].set_color(get_color_from_hex('#000000')) #黒色を設定 return self.painter def clear_canvas(self): self.painter.ids['paint_area'].canvas.clear() self.painter.ids['paint_area'].set_color(self.painter.ids['paint_area'].last_color) def save_canvas(self): filename_base = 'sample.png' img_path = Window.screenshot("base\" + filename_base) # スクリーンショットを保存する basename = os.path.basename(img_path) img = cv2.imread("base\" + basename) cv2.rectangle(img, (0, 0), (78, 39), (255, 255, 255), thickness=-1) img = img[0:637, 0:1024] clip.mask_and_alpha(img, clip.maskgenerate(img, basename), basename) class ColorButton(ToggleButton): def _do_press(self): if self.state == 'normal': ToggleButtonBehavior._do_press(self)# ボタンを押されてない場合は状態を変更する if __name__ == '__main__': Window.clearcolor = get_color_from_hex('#ffffff') # ウィンドウの色を白色に変更する MyPaintApp().run()

clip.py

import numpy as np import cv2 #関数定義 def cannyprocess(img, basename): edges = cv2.Canny(img,100,101,None, 3, True) cv2.imwrite("canny\" + basename,edges)#エッジ画像保存 can_img = cv2.imread("canny\" + basename)#エッジ画像の読み込み return can_img def contourprocess(img): gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) print(hierarchy) return contours def maskgenerate(img, basename): back = np.zeros_like(img) cont = contourprocess(cannyprocess(img,basename)) mask = cv2.drawContours(back, cont, -1, color=(255, 255, 255), thickness=-1) cv2.imwrite("mask\" + basename,mask) mask = cv2.imread("mask\" + basename,0) return mask def mask_and_alpha(base_img, mask_img, basename): bgr_img = cv2.split(base_img) clip = cv2.merge(bgr_img + [mask_img]) cv2.imwrite("clip\" + basename,clip) return clip #関数定義

mypaint.kv

#:import hex_color kivy.utils.get_color_from_hex <ColorButton>: background_normal: 'color_button_normal.png' background_down: 'color_button_down.png' group: 'color' border: (5, 5, 5, 5) on_release: app.painter.ids['paint_area'].set_color(self.background_color) #on_release: app.painter.paint_id.set_color(self.background_color) # こ�?�方法でもset_corlorにアクセス可能 <MyCanvasWidget>: paint_id:paint_area id: canvas_area test:button1 Button: text: 'save' color: 1, 1, 1 , 1 font_size: 20 on_release: app.save_canvas() border: (2, 2, 2, 2) x: 0 top: root.top width: 80 height: 40 BoxLayout: orientation: 'vertical' height: root.height width: root.width MyPaintWidget: id: paint_area size_hint_y: 0.8 BoxLayout: orientation: 'horizontal' size_hint_y: 0.1 Label: size_hint_x: 0.1 text: 'Line width %s' % int(s1.value) if s1.value else 'Line width not set' color: 0,0,0,1 Slider: id: s1 size_hint_x: 0.9 value: 3 range: (1,100) step: 1 on_touch_down:app.painter.ids['paint_area'].set_line_width(self.value) BoxLayout: orientation: 'horizontal' size_hint_y: 0.1 clear_btn:button1 Button: id: button1 text: "Clear" ont_size: 30 on_release: app.clear_canvas() ColorButton: text: "white " color: 0, 0, 0 , 1 background_color: hex_color('#ffffff') ColorButton: text: "black " state: 'down' background_color: hex_color('#000000') ColorButton: text: "red " background_color: hex_color('#ff0000') ColorButton: text: "biue " background_color: hex_color('#0000ff') ColorButton: text: "green " background_color: hex_color('#008000') ColorButton: text: "orange" background_color: hex_color('#ff4500') ColorButton: text: "purple" background_color: hex_color('#800080')

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

マスク画像

でで示されている絵で言えば,目的は
その魚(?)の外周の内側領域を全て白にできれば達成できるという話でしょうか.
であれば…

  • findContoursの処理対象をcannyで作るのは後段処理が面倒になりそうな気がします.
    普通にthresholdで2値化してはどうでしょう.
    その際,findContoursで使うことを考慮して,背景が黒になるようにTHRESH_BINARY_INVを指定すると良いかと.
  • 前記THRESH_BINARY_INVを用いた2値化結果にfindContoursを(現コードと同様にRETR_EXTERNALを指定して)行えば,所望の結果が得られるのではないでしょうか.

投稿2019/08/07 01:35

fana

総合スコア11656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/08/07 04:40

完成できました 適切な解答ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問