SORU
17 NİSAN 2012, Salı


Nasıl Sudoku bir kare içinde sürekli kusurları kaldırmak için?

Eğlenceli bir proje yapıyordum: bir giriş görüntüden bir Sudoku OpenCV (Google gözlük vb.) kullanarak. Çözme Ve görevi tamamladım, ama sonunda kendisi için buraya geldiğim küçük bir sorun buldum.

Programlama OpenCV 2.3.1 Python API kullanarak yaptım.

Yaptıklarım aşağıda :

  1. Resim okumak
  2. Hatlarını bulmak
  3. Maksimum alan, ( ve biraz da eşdeğeri) Kare olanı seçin.
  4. Köşe noktaları bulmak.

    örneğin aşağıda verilmiştir:

    enter image description here

    (Yeşil hat Sudoku doğru eğrilmiş olabilir doğru Sudoku gerçek sınırlara da uygun düşüyor, buraya dikkat edin. Kontrol bir sonraki resim)

  5. mükemmel bir kare resim warp

    görüntü örn:

    enter image description here

  6. OCR için Simple Digit Recognition OCR in OpenCV-Python verdim yöntemini kullandım () gerçekleştirin

Ve bu yöntem işe yaradı.

Sorun:

this image. Check out

Bu görüntü üzerinde 4 adımı gerçekleştirmek aşağıdaki sonucu verir:

enter image description here

Kırmızı çizgi çizilmiş sudoku sınır gerçek anahat olan orijinal kontur.

Yeşil hat çizilmiş çarpık görüntünün anahat olacak yaklaşık dağılımı.

Tabii ki, sudoku üst kenarında yeşil hat ve kırmızı hat arasında fark yoktur. Çözgü ederken, Sudoku orijinal sınır almıyorum.

Sorum Şu :

Nasıl Sudoku doğru sınırında görüntü, yani kırmızı çizgi YA da nasıl kırmızı hat ve yeşil hat arasında fark kaldırabilirim warp miyim? OpenCV bunun için herhangi bir yöntem var mı?

CEVAP
6 Temmuz 2012, Cuma


Nikie cevabı benim sorunum çözüldü, ama onun cevabı İncelenmiştir. OpenCV kendi adaptasyon burada vermem gerektiğini düşündüm. Ama uygulamadan sonra OpenCV kodu nikie. * kod çok daha büyük olduğunu görebiliyordum. Ve ayrıca, aradeğerleme yöntemi OpenCV içinde nikie ( scipy kullanarak yapmış olabilir olsa da, zamanı gelince anlatacağım.) tarafından yapılır bulamadım

1. Görüntü Önişleme ( kapatma işlemi )

import cv2
import numpy as np

img = cv2.imread('dave.jpg')
img = cv2.GaussianBlur(img,(5,5),0)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
mask = np.zeros((gray.shape),np.uint8)
kernel1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11))

close = cv2.morphologyEx(gray,cv2.MORPH_CLOSE,kernel1)
div = np.float32(gray)/(close)
res = np.uint8(cv2.normalize(div,div,0,255,cv2.NORM_MINMAX))
res2 = cv2.cvtColor(res,cv2.COLOR_GRAY2BGR)

Sonuç :

Result of closing

2. Sudoku Kare bulma ve Maske Görüntü Oluşturma

thresh = cv2.adaptiveThreshold(res,255,0,1,19,2)
contour,hier = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

max_area = 0
best_cnt = None
for cnt in contour:
    area = cv2.contourArea(cnt)
    if area > 1000:
        if area > max_area:
            max_area = area
            best_cnt = cnt

cv2.drawContours(mask,[best_cnt],0,255,-1)
cv2.drawContours(mask,[best_cnt],0,0,2)

res = cv2.bitwise_and(res,mask)

Sonuç :

enter image description here

3. Dikey çizgiler bulma

kernelx = cv2.getStructuringElement(cv2.MORPH_RECT,(2,10))

dx = cv2.Sobel(res,cv2.CV_16S,1,0)
dx = cv2.convertScaleAbs(dx)
cv2.normalize(dx,dx,0,255,cv2.NORM_MINMAX)
ret,close = cv2.threshold(dx,0,255,cv2.THRESH_BINARY cv2.THRESH_OTSU)
close = cv2.morphologyEx(close,cv2.MORPH_DILATE,kernelx,iterations = 1)

contour, hier = cv2.findContours(close,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contour:
    x,y,w,h = cv2.boundingRect(cnt)
    if h/w > 5:
        cv2.drawContours(close,[cnt],0,255,-1)
    else:
        cv2.drawContours(close,[cnt],0,0,-1)
close = cv2.morphologyEx(close,cv2.MORPH_CLOSE,None,iterations = 2)
closex = close.copy()

Sonuç :

enter image description here

4. Yatay Çizgiler Bulma

kernely = cv2.getStructuringElement(cv2.MORPH_RECT,(10,2))
dy = cv2.Sobel(res,cv2.CV_16S,0,2)
dy = cv2.convertScaleAbs(dy)
cv2.normalize(dy,dy,0,255,cv2.NORM_MINMAX)
ret,close = cv2.threshold(dy,0,255,cv2.THRESH_BINARY cv2.THRESH_OTSU)
close = cv2.morphologyEx(close,cv2.MORPH_DILATE,kernely)

contour, hier = cv2.findContours(close,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contour:
    x,y,w,h = cv2.boundingRect(cnt)
    if w/h > 5:
        cv2.drawContours(close,[cnt],0,255,-1)
    else:
        cv2.drawContours(close,[cnt],0,0,-1)

close = cv2.morphologyEx(close,cv2.MORPH_DILATE,None,iterations = 2)
closey = close.copy()

Sonuç :

enter image description here

Tabii ki, bu çok iyi değil.

5. Izgara Noktaları Bulmak

res = cv2.bitwise_and(closex,closey)

Sonuç :

enter image description here

6. Kusurları düzeltmek

Burada, nikie hakkında çok fazla bilgim yok ilişkilendirme, bir tür yapar. Ve bu OpenCV için ilgili herhangi bir fonksiyon bulamadım. (Mayıs olur, bilmiyorum).

Kullanmak istemiyorum bu nasıl SciPy kullanarak açıklıyor bu SOF bak,: Image transformation in OpenCV

Yani, burada her sub-kare ve uygulamalı warp Bakış açısı her 4 köşe aldım.

Bunun için, ilk sentroidler buluruz.

contour, hier = cv2.findContours(res,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
centroids = []
for cnt in contour:
    mom = cv2.moments(cnt)
    (x,y) = int(mom['m10']/mom['m00']), int(mom['m01']/mom['m00'])
    cv2.circle(img,(x,y),4,(0,255,0),-1)
    centroids.append((x,y))

Ancak sonuç sentroidler sıralanmış olmayacak. Resme bak sıralarını görmek için:

enter image description here

Biz sağdan sola doğru sıralayın yani, yukarıdan aşağıya.

centroids = np.array(centroids,dtype = np.float32)
c = centroids.reshape((100,2))
c2 = c[np.argsort(c[:,1])]

b = np.vstack([c2[i*10:(i 1)*10][np.argsort(c2[i*10:(i 1)*10,0])] for i in xrange(10)])
bm = b.reshape((10,10,2))

Şimdi bunların sırası aşağıya bakın :

enter image description here

Son olarak biz bu dönüşümü uygulamak ve boyutta yeni bir görüntü 450x450 oluşturun.

output = np.zeros((450,450,3),np.uint8)
for i,j in enumerate(b):
    ri = i/10
    ci = i
    if ci != 9 and ri!=9:
        src = bm[ri:ri 2, ci:ci 2 , :].reshape((4,2))
        dst = np.array( [ [ci*50,ri*50],[(ci 1)*50-1,ri*50],[ci*50,(ri 1)*50-1],[(ci 1)*50-1,(ri 1)*50-1] ], np.float32)
        retval = cv2.getPerspectiveTransform(src,dst)
        warp = cv2.warpPerspective(res2,retval,(450,450))
        output[ri*50:(ri 1)*50-1 , ci*50:(ci 1)*50-1] = warp[ri*50:(ri 1)*50-1 , ci*50:(ci 1)*50-1].copy()

Sonuç :

enter image description here

Sonuç yok, ama kod uzunluğu büyük olduğu için nikie hemen hemen aynı. Daha iyi yöntemler var olabilir, ama o zamana kadar, bu TAMAM çalışır.

Saygılar ARK.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Alexander Johnson

    Alexander Jo

    26 Temmuz 2008
  • Gavin Hoey

    Gavin Hoey

    21 Aralık 2007
  • gsipek

    gsipek

    20 Temmuz 2007