मेरे पास कई पीएनजी फाइलें हैं और मैं बहुभुज समोच्च निर्देशांक प्राप्त करने का प्रयास कर रहा हूं। यह सरलीकृत निर्देशांक है, केवल प्रत्येक बाहरी कोने (उत्तल पतवार बहुभुज नहीं)।

प्रोग्राम जो इस समय ऐसा करेगा वह है पायथन और ओपनसीवी। लेकिन एक और कार्यक्रम ठीक है मैंने एनपीएम पैकेज, इमेजमैजिक, पोट्रेस, लुआ का उपयोग करके इसे ठीक करने का प्रयास किया। इसे 'छवियों से बहुभुज बनाएं' प्रक्रिया में शेल कमांड के रूप में उपयोग किया जाएगा।

पायथन के तहत यह आखिरी टेस्ट था।

अब समस्या यह है कि नीचे के उदाहरण में कुछ किनारे 'नहीं' सही हैं।

मैंने निम्नलिखित कदम उठाए:

  • अल्फा को ब्लैक एंड व्हाइट में बदलें
  • समोच्च का पता लगाएं
  • निर्देशांक प्राप्त करें
  1. मूल पीएनजी फ़ाइल में काली रेखाएँ हैं (उन्हें रखें)।

Original png

  1. परिवर्तित श्वेत और श्याम छवि (आप शीर्ष पंक्ति नहीं देख सकते, क्योंकि इस वेबसाइट की पृष्ठभूमि सफेद है)
ret, mask = cv2.threshold(img[:, :, 3], 0, 255, cv2.THRESH_BINARY)

Converted png

  1. ट्रेस किए गए समोच्च रूपरेखा (वह आउटपुट नहीं जो मुझे चाहिए)
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

traced image

समस्या दो छेद हैं, 1 पिक्सेल बाएँ और 1 पिक्सेल दाएँ गायब है।

problem zoom detail

  1. जब मैं किसी अन्य प्रोग्राम के अंदर उस समोच्च डेटा का उपयोग करता हूं तो आपको यह मिलता है:

external polygon

  1. मुझे यह समोच्च रूपरेखा बहुभुज डेटा चाहिए, इसलिए बाहरी कार्यक्रम यह दिखाता है:

output I want

# https://opensource.com/article/19/5/python-3-default-mac#what-to-do
# https://solarianprogrammer.com/2019/10/21/install-opencv-python-macos/
# https://docs.opencv.org/master/d4/d73/tutorial_py_contours_begin.html
# https://stackoverflow.com/questions/25733694/process-image-to-find-external-contour
# https://docs.opencv.org/3.4/dd/d49/tutorial_py_contour_features.html
# https://stackoverflow.com/questions/39823221/imagemagick-find-coordinates-of-outline-of-transparent-png-not-border

import numpy as np
import cv2

img = cv2.imread('../temp/bord.png', cv2.IMREAD_UNCHANGED)

# make black and white
ret, mask = cv2.threshold(img[:, :, 3], 0, 255, cv2.THRESH_BINARY)

# find the external contour
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# at this point I want to have the correct contours to process them inside a other program
# print(contours)

# start debugging
#save image
cv2.imwrite('../temp/bord_converted.png',mask) 


#create an empty image for contours
img_contours = np.zeros(img.shape)
# draw the contours on the empty image
cv2.drawContours(img_contours, contours, -1, (0,255,0), 1)
cv2.imwrite('../temp/bord_contour.jpg',img_contours) 

संपादित करें

अन्य चीजें जो मैंने कोशिश की:

मार्चिंग स्क्वायर कार्यक्रम

गोलंग

https://github.com/zx9597446/marchingsquare/issues/1 वह मुझे एक और समस्या देता है, लेकिन सही कोड

एनपीएम https://github.com/scottglz/image-outline वह मुझे लगभग ऊपर की तरह ही समस्या देता है

इमेजमैजिक

पीएनजी को काले/और सफेद में परिवर्तित करने और रूपरेखा वापस करने के लिए कुछ चीजों की कोशिश कर रहा था।

convert "$IMAGE" -matte -bordercolor none -border 1 -alpha extract -edge 1 -threshold 50% -depth 8 txt: | awk -F: '/white/{print $1}'

पोट्रेस

लेकिन सभी आउटपुट में चीजें हैं इसलिए मैं इसका उपयोग नहीं कर सकता।

potrace --progress -b svg --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --group --flat ../temp/bordout.bmp -o ../temp/bordout.svg
potrace --progress -b eps -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.eps
potrace --progress -b pdf -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pdf
potrace --progress -b pdfpage --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pdfpage
potrace --progress -b ps -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.ps
potrace --progress -b pgm --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pgm
potrace --progress -b dxf --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.dxf
potrace --progress -b geojson --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.geojson
potrace --progress -b gimppath --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.gimppath
potrace --progress -b xfig --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.xfig

उदाहरण के लिए एसवीजी आउटपुट एक तस्वीर के रूप में सही दिखता है लेकिन मैं इसे एक्स, वाई पॉइंट सरणी बहुभुज में परिवर्तित नहीं कर सकता।

<path d="M121 132 l-121 0 0 -66 0 -66 121 0 121 0 0 66 0 66 -121 0z m0 -1
l120 0 0 -22 0 -23 -10 0 -11 0 0 -42 0 -43 -5 0 -5 0 0 43 0 42 -89 0 -89 0
0 -42 0 -43 -5 0 -5 0 0 43 0 42 -10 0 -11 0 0 23 0 22 120 0z M121 130 l-119
0 0 -21 0 -22 11 0 10 0 0 -42 0 -43 4 0 4 0 0 43 0 42 90 0 90 0 0 -42 0 -43
4 0 4 0 0 43 0 42 11 0 10 0 0 22 0 21 -119 0z"/>
</g>

https://github.com/Phrogz/svg-path-to-polygons उदाहरण के लिए मुझे देता है

[
  [
    [ 121, 132 ], [ 0, 132 ],
    [ 0, 66 ],    [ 0, 0 ],
    [ 121, 0 ],   [ 242, 0 ],
    [ 242, 66 ],  [ 242, 132 ],
    [ 121, 132 ], [ 121, 132 ],
    closed: true
  ],
  [
    [ 121, 131 ], [ 241, 131 ], [ 241, 109 ],
    [ 241, 86 ],  [ 231, 86 ],  [ 220, 86 ],
    [ 220, 44 ],  [ 220, 1 ],   [ 215, 1 ],
    [ 210, 1 ],   [ 210, 44 ],  [ 210, 86 ],
    [ 121, 86 ],  [ 32, 86 ],   [ 32, 44 ],
    [ 32, 1 ],    [ 27, 1 ],    [ 22, 1 ],
    [ 22, 44 ],   [ 22, 86 ],   [ 12, 86 ],
    [ 1, 86 ],    [ 1, 109 ],   [ 1, 131 ],
    [ 121, 131 ], [ 121, 131 ], closed: true
  ],
  [
    [ 121, 130 ], [ 2, 130 ],   [ 2, 109 ],
    [ 2, 87 ],    [ 13, 87 ],   [ 23, 87 ],
    [ 23, 45 ],   [ 23, 2 ],    [ 27, 2 ],
    [ 31, 2 ],    [ 31, 45 ],   [ 31, 87 ],
    [ 121, 87 ],  [ 211, 87 ],  [ 211, 45 ],
    [ 211, 2 ],   [ 215, 2 ],   [ 219, 2 ],
    [ 219, 45 ],  [ 219, 87 ],  [ 230, 87 ],
    [ 240, 87 ],  [ 240, 109 ], [ 240, 130 ],
    [ 121, 130 ], [ 121, 130 ], closed: true
  ]
]

संपादित करें २

जब मैं एसवीजी समाधान का उपयोग करता हूं तो आउटपुट मुझे अब एक पठनीय बिंदु सूची देता है

<polygon fill="none" points="0,0 0,44 20,44 21,45 21,129 30,129 30,45 31,44 208,44 209,45 209,129 218,129 218,45 219,44 239,44 239,0" stroke="black" stroke-linecap="round" stroke-linejoin="miter" />

लेकिन जब मैं उस समन्वय सूची का उपयोग करता हूं तो यह 100% सही नहीं होता है। कोने अभी भी सही नहीं हैं।

फ़ायरफ़ॉक्स के साथ आउटपुट (ज़ूम इन) यह दिखाएगा:

firefox output

और वह कार्यक्रम जहां मैं समन्वय सूची का उपयोग करूंगा (एसवीजी नहीं)

love.graphics.polygon("line",0,0,0,44,20,44,21,45,21,129,30,129,30,45,31,44,208,44,209,45,209,129,218,129,218,45,219,44,239,44,239,0)

आउटपुट होगा:

love2d output

संपादित करें 3

अंतिम पायथन लिपि का उपयोग करके बहुभुज नहीं बनाते हैं।

program output

1
gcmartijn 27 सितंबर 2020, 09:58

1 उत्तर

सबसे बढ़िया उत्तर

वांछित आउटपुट: वेक्टर ग्राफिक

वेक्टर ग्राफ़ में बिंदुओं, रेखाओं और वक्रों को बिना किसी अलियासिंग के किसी भी रिज़ॉल्यूशन तक बढ़ाया या घटाया जा सकता है। ऐसे में आपको टूटे हुए कोने नजर नहीं आएंगे। मान लीजिए कि आउटपुट एसवीजी प्रारूप में एक वेक्टर ग्राफ है। प्रत्येक समोच्च को एक एसवीजी बहुभुज में परिवर्तित करके कोनों को अच्छी तरह से देखा जा सकता है। रेंडर करने के तीन विकल्पों के लिए आप यहां देख सकते हैं कोनों। मैं पर्याप्त बिंदुओं को समायोजित करने के लिए add_pixel_fillers फ़ंक्शन भी जोड़ता हूं।

import cv2
import svgwrite

img = cv2.imread("WFVso.png", cv2.IMREAD_UNCHANGED)
ret, mask = cv2.threshold(img[:, :, 3], 0, 255, cv2.THRESH_BINARY)

def add_pixel_fillers(img, cnt):
    n_points = len(cnt)
    for idx in range(n_points):
        prev_pt = cnt[(idx+n_points+1) % n_points]
        next_pt = cnt[(idx+1) % n_points]
        if abs(cnt[idx][0]-next_pt[0])==1 and abs(cnt[idx][1]-next_pt[1])==1:
            temp_x, temp_y = max(cnt[idx][0], next_pt[0]), min(cnt[idx][1], next_pt[1])
            if img[temp_y, temp_x] == 255:
                cnt[idx][0] = temp_x
                cnt[idx][1] = temp_y
            else:
                temp_x, temp_y = min(cnt[idx][0], next_pt[0]), max(cnt[idx][1], next_pt[1])
                if img[temp_y, temp_x] == 255:
                    cnt[idx][0] = temp_x
                    cnt[idx][1] = temp_y
    return cnt

contours, hierarchy = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

h, w = width=img.shape[0], img.shape[1]
dwg = svgwrite.Drawing('test.svg', height=h, width=w, viewBox=(f'-10 -10 {h} {w}'))
for cnt in contours:
    cnt = add_pixel_fillers(mask, cnt.squeeze().tolist())
    dwg.add(dwg.polygon(
        points=cnt,
        stroke_linecap='round',
        stroke='black',
        fill='none',
        stroke_linejoin='miter'
        ))
dwg.save()

उदाहरण इनपुट का एसवीजी आउटपुट है

<?xml version="1.0" encoding="utf-8" ?>
<svg baseProfile="full" height="100%" version="1.1" viewBox="-10 -10 130 240" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs />
<polygon fill="none" points="0,0 0,44 21,44 21,45 21,129 30,129 31,44 31,44 209,44 209,45 209,129 218,129 219,44 219,44 239,44 239,0" stroke="black" stroke-linecap="round" stroke-linejoin="miter" />
</svg>

Output Image

वांछित आउटपुट: रेखापुंज ग्राफिक

कोनों में लापता पिक्सेल कैसे भरें? मान लीजिए कि आपको दिए गए मामलों में केवल 90 डिग्री पर कोनों को संभालने की आवश्यकता है, केवल सीमित संख्या में पिक्सेल पैटर्न होंगे जहां आप लापता पिक्सेल भरना चाहते हैं। उन प्रतिमानों को देखते हुए, आप यह पता लगाने के लिए scipy पैकेज में ndimage.correlate फ़ंक्शन का उपयोग कर सकते हैं कि पिक्सेल कहाँ भरना है।

नमूना कोड

import numpy as np
from scipy import ndimage
# Assume this is the contour you obtained in step 3
img = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                [1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 1, 0, 0, 0, 0, 1, 1, 1],
                [0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
                [0, 0, 1, 0, 0, 0, 1, 0, 0, 0]])

# You can add the patterns here
patterns = [
    np.array([[0,0,0,0,0],
              [0,0,0,0,0],
              [1,1,0,0,0],
              [0,0,1,0,0],
              [0,0,1,0,0]]),
    np.array([[0,0,0,0,0],
              [0,0,0,0,0],
              [0,0,0,1,1],
              [0,0,1,0,0],
              [0,0,1,0,0]])]

missing_corners = np.zeros_like(img) #Result will be stored here
for patt in patterns:
    result = ndimage.correlate(img, patt, mode="constant")
    corners = np.floor(result/np.sum(patt)).astype(int)
    missing_corners = (missing_corners + corners) % 2 #Can use binary OR

परिणाम देखने के लिए

print(missing_corners)

लापता कोने के स्थान दिखाएगा:

array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

अधिक जटिल आकृतियों के लिए, मेरा सुझाव है कि जब आप समोच्च निर्यात करते हैं तो drawSvg जैसे पैकेजों का उपयोग करके वेक्टर चित्र (जैसे SVG) उत्पन्न करें।

0
Paco Wong 5 अक्टूबर 2020, 03:57