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

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

ただいまの
回答率

91.26%

  • Python 3.x

    2744questions

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

  • OpenCV

    670questions

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

  • Windows 10

    597questions

    Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

SVMでコマの検出をしたい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 59

shinya_next

score 8

漫画のコマを検出したいと思っております。外接矩形の面積を特徴量としてSVMを用いてコマの検出をしたいと考えておりますが、どう実装したらいいのかわかりません。詳しく教えてください。

import cv2
import numpy as np
from PIL import Image
import glob
import matplotlib.pyplot as plt
import os 
import sys
import math
from siro import *
import random


# 白黒反転
def loadfile():

    files = os.listdir(''C:\\Users\\file\\pic3')

    length=len(files)-1
    print(files)
    for i  in range(length):
        print(i)
        filename=files[i]
        logfilename="pic3/"+filename
        img=cv2.imread(logfilename)
        #cv2.imshow('image', img)     
        gray =cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        #mask2=cv2.bitwise_not(gray)
        name=  gray.copy()
        t =127
        name[gray < t]  = 0
        name[gray >= t] = 255           
        #mask2=cv2.bitwise_not(name)
        outputfn="opicture/"+"outputpic"+str(i)+".jpg"
        cv2.imwrite(outputfn,name)



# 二値化
def area():
    files = os.listdir('C:\\Users\\file\\opicture')
    print(files)
    length=len(files)-1
    allw=[]
    for i  in range(length):
        filename=files[i]
        logfilename="opicture/"+filename
        #logfilename="input.png"

        img2=cv2.imread(logfilename)
        img3=cv2.cvtColor(img2,cv2.COLOR_BGR2HSV)


        # 面積(white)
        hsv_min = np.array([0, 0, 255]) 
        hsv_max = np.array([0, 0, 255]) 
        mask = cv2.inRange(img3, hsv_min,  hsv_max)
        white= cv2.countNonZero(mask)


        total=mask.shape[0]*mask.shape[1]
        black=total-white

        # 白の面積が黒の面積より広い場合は再度白黒を反転する
        if white>black:       
             mask2=cv2.bitwise_not(img2)
             name2= mask2.copy()
             t = 127             
             name2[mask2 < t]  = 0
             name2[mask2 >= t] = 255    

             os.remove(logfilename)

             cv2.imwrite(logfilename, name2) 

             pre=black
             black=white
             white=pre
             a=[total,white]
             allw.append(a)
        else:
            a=[filename,total,white]
            allw.append(a)


    return allw



# 周囲長(permister)    
def  perimister ():
    files = os.listdir('C:\\Users\\file\\opicture')

    length=len(files)-1
    allw=[]

    for i  in range(length):
        filename=files[i]
        logfilename="opicture/"+filename
        #logfilename="input.png"
        print(logfilename)
        img2=cv2.imread(logfilename)
        img3=cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
        ret,thresh = cv2.threshold(img3,127,255,0)
        #cv2.imshow("th",thresh)
        imgEdge,contours,hierarchy = cv2.findContours(thresh, 1, 2)

        imgEdge,contours,hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        imagecounter1 = np.copy(img2)
        min_coin_area =0.1
        large_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > min_coin_area]
        img4=cv2.drawContours( imagecounter1, large_contours, -1, (0,0,255),1)
        outputfn="opicture2/"+"out2putpic"+str(i)+".jpg"
        cv2.imwrite(outputfn,img4)
        warea=0
        permister=0
        for contour in large_contours: 
           area = cv2.contourArea(contour)
           per=cv2.arcLength(contour,True)
           warea+=area
           permister+=per

        imagecounter2 = np.copy(img2) 
        imagecounter8 = np.copy(img2) 
        acx=0
        acy=0

        a=[]
        print(large_contours)
        """
        # 重心
        for contour in large_contours:
             M = cv2.moments(contour)
             cx = int(M['m10']/M['m00'])
             cy = int(M['m01']/M['m00'])
             img12=cv2.circle(imagecounter2, (cx,cy), 3,(0,0,255), -1)
             ab=[cx,cy]
             a.append(ab)
             acx+=cx
             acy+=cy
        acx=int(acx/len(large_contours))
        acy=int(acy/len(large_contours))    
        img10=cv2.circle(imagecounter8, (acx,acy),1,(0,255,0), 2)
        outputfn="opicture2/"+"Mout10putpic"+str(i)+".jpg"
        cv2.imwrite(outputfn,img10)    
        outputfn="opicture2/"+"Mout5putpic"+str(i)+".jpg"
        cv2.imwrite(outputfn,img12)    
        print(a)



        imagecounter2 = np.copy(img2) 
        j=0
        print(len(a))
        zyusin=[]
        ar=[0]
        while 1:
            try1=a[j]
            x=try1[0]
            y=try1[1]
            w=1
            arc=[]
            #ar.remove(j)
            while 1:
                if any(w==arr for arr in ar ):
                    True

                try:

                    try2=a[w+j]
                    x2=try2[0]
                    y2=try2[1]
                    cx=abs(x-x2)
                    cy=abs(y-y2)
                    root=math.sqrt((cx*cx)+(cy*cy))

                    print("-------------")
                    print(j)
                    print(w+j)
                    print(root)
                    print("-------------")

                    if root<=20:
                        print("a")
                        ar.append(w)
                        arc.append([x2,y2])                                              
                        print(arc)
                        w+=1;    
                    if root>20:
                         w+=1
                except IndexError:
                    print(arc)

                    start=try1
                    while 1:
                        try:
                            a1=random.choice(arc)
                            arc.remove(a1)
                        except IndexError:
                            zyu=[try1[0],try1[1]]
                            zyusin.append(zyu)
                            break;
                        try:
                            a2=random.choice(arc)
                            arc.remove(a2)
                            acx=(a1[0]+a2[0]+start[0])/3
                            acy=(a1[1]+a2[1]+start[1])/3
                            start=[acx,acy]
                        except IndexError:
                            x=(a1[0]+try1[0])/2
                            y=(a1[1]+try1[1])/2
                            zyu=[x,y]
                            print(zyu)
                            zyusin.append(zyu)
                            break;
                        if len(arc)==0:
                            zyu=[acx,acy]
                            zyusin.append(zyu)
                            print(zyu)

                            break;    


                    j+=1
                    break ;

            if j>=len(a):
                break;

        print(zyusin)

        for r in range(len(zyusin)):
            x=int(zyusin[r][0])
            y=int(zyusin[r][1])
            img11=cv2.circle(imagecounter2, (x,y), 4,(200,200,200), 2, 4)
        outputfn="opicture2/"+"Mout32putpic"+str(i)+".jpg"
        cv2.imwrite(outputfn,img11)  
        #sys.exit()
        """


        # 回転を考慮しない外接矩形(辺長、面積)
        imagecounter2 = np.copy(img2)
        aarea=0
        per1=0
        print("---------------")
        for contour in large_contours:
                x, y, w, h = cv2.boundingRect(contour)
                aarea=aarea+(w*h)                
                per1=per1+(2*w+2*h)
                img5=cv2.rectangle(imagecounter2 , (x, y), (x + w, y + h), (0, 255, 0), 2)
        percent=warea/aarea                


        outputfn="opicture3/"+"out2putpic"+str(i)+".jpg"
        cv2.imwrite(outputfn,img5)




        # 回転を考慮した外接矩形
        imagecounter3 = np.copy(img2)
        for contour in large_contours:     
                rect = cv2.minAreaRect(contour)
                box = cv2.boxPoints(rect)
                box = np.int0(box)



                img6 = cv2.drawContours(imagecounter3,[box],0,(255,0,0),3)                
        outputfn="opicture4/"+"out3putpic"+str(i)+".jpg"
        cv2.imwrite(outputfn,img6)



        # 外接円の円周の長さと面積(permister2、menseki3)
        imagecounter4 = np.copy(img2)
        permister2=0
        menseki3=0
        for contour in large_contours:     
              (x,y),radius = cv2.minEnclosingCircle(contour)
              center = (int(x),int(y))
              radius = int(radius)
              permister2=permister2+(2*radius*math.pi)
              menseki3=menseki3+(radius*radius*math.pi)
              img7= cv2.circle(imagecounter4,center,radius,(0,255,0),2)

        outputfn="opicture5/"+"out3putpic"+str(i)+".jpg"
        cv2.imwrite(outputfn,img7)



           return allw   



if __name__ == "__main__":

    loadfile()
    allw=area()
    allw2=perimister ()
    print(allw2)        
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

入力が面積だけなら、そもそもSVMを使うようなタスクではないのでは?
適当に閾値を設定して、それ以上に大きい矩形をコマとみなせばいいような...

コメントを受けて

適当にググってみても、画像処理だけで充分対処できているようです。
機械学習で対処したいのなら、CNNに放り込んでコマ割りを得る、みたいのは可能かもしれませんが。
その場合矩形検出は不要でしょう。

よほど前衛的なコマ割りをしていない限り、単に矩形検出で済むように思います。
矩形の面積を入力にしたとしても、境界が非線形になるとは思えないんですよね。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/23 18:19

    面積と直線検出から算出したいと思っています。SVMを用いてコマを割り出したいのです。

    キャンセル

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

ただいまの回答率

91.26%

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    2744questions

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

  • OpenCV

    670questions

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

  • Windows 10

    597questions

    Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。