gnuplot: कैसे कोई मार्जिन के साथ पिक्सेल प्रति एक 2D सरणी तत्व साजिश करने के लिए


9

मैं gnuplot 5.0 का उपयोग करने की कोशिश कर रहा हूं ताकि कोई मार्जिन या सीमाओं या कुल्हाड़ियों के साथ डेटा का 2 डी सरणी प्लॉट किया जा सके ... बस एक 2D छवि (.png या .jpg) कुछ डेटा का प्रतिनिधित्व करता है। मैं प्रत्येक सरणी तत्व को छवि में एक स्केलिंग / इंटरपोलेशन आदि के साथ बिल्कुल एक पिक्सेल के अनुरूप बनाना चाहता हूं और किनारों पर कोई अतिरिक्त सफेद पिक्सेल नहीं।

अब तक, जब मैं मार्जिन को 0 पर सेट करने की कोशिश करता हूं और यहां तक ​​कि pixelsझंडे का उपयोग करते हुए , मैं अभी भी छवि के दाईं और शीर्ष सीमाओं पर सफेद पिक्सेल की एक पंक्ति के साथ छोड़ दिया जाता हूं।

मैं डेटा सरणी के पिक्सेल-बाय-पिक्सेल प्रतिनिधित्व के साथ सिर्फ एक छवि फ़ाइल कैसे प्राप्त कर सकता हूं और अतिरिक्त कुछ भी नहीं?

सूक्ति शास्त्र:

#!/usr/bin/gnuplot --persist

set terminal png size 400, 200

set size ratio -1
set lmargin at screen 0
set rmargin at screen 1
set tmargin at screen 0
set bmargin at screen 1

unset colorbox
unset tics
unset xtics
unset ytics
unset border
unset key

set output "pic.png"

plot "T.dat" binary array=400x200 format="%f" with image pixels notitle

फोरट्रान 90 का उदाहरण डेटा:

program main
implicit none
integer, parameter :: nx = 400
integer, parameter :: ny = 200
real, dimension (:,:), allocatable :: T
allocate (T(nx,ny))

T(:,:)=0.500
T(2,2)=5.
T(nx-1,ny-1)=5.
T(2,ny-1)=5.
T(nx-1,2)=5.

open(3, file="T.dat", access="stream")
write(3) T(:,:)
close(3)

end program main

अतिरिक्त पिक्सेल


यदि डेटा x y zसूची प्रारूप में है तो क्या यह स्वीकार्य होगा ?
Theozh

जवाबों:


5

कुछ gnuplot टर्मिनल छवि के साथ एक अलग png फ़ाइल बनाकर और फिर परिणामी भूखंड के अंदर इसे लिंक करके "छवि के साथ" लागू करते हैं। सीधे उस अलग पिंग इमेज फ़ाइल का उपयोग करने से पेज लेआउट, मार्जिन आदि के किसी भी मुद्दे से बचना होगा। यहां मैं कैनवास टर्मिनल का उपयोग करता हूं। साजिश खुद को दूर फेंक दिया जाता है; हम सभी रखते हैं वांछित सामग्री के साथ बनाई गई png फ़ाइल।

gnuplot> set term canvas name 'myplot'
Terminal type is now 'canvas'
Options are ' rounded size 600,400 enhanced fsize 10 lw 1 fontscale 1 standalone'
gnuplot> set output '/dev/null'
gnuplot> plot "T.dat" binary array=400x200 format="%f" with image 
   linking image 1 to external file myplot_image_01.png
gnuplot> quit

$identify myplot_image_01.png
myplot_image_01.png PNG 400x200 400x200+0+0 8-bit sRGB 348B 0.000u 0:00.000

यह छोटा और तेज़ और काम करता है! केवल वही चीजें जो मैं अभी तक सफल नहीं हुआ हूं: 1. विंडोज में आउटपुट से बचें, 2. अपना खुद का नाम इंडेक्स के बिना png फाइल में दें या कम से कम png फाइल के इंडेक्स को बढ़ाने से रोकें जब आप प्लॉट को फिर से बनाते हैं।
theozh

मैं विंडोज आउटपुट के साथ मदद नहीं कर सकता। आप कैनवास टर्मिनल में काउंटर के बारे में सही हैं; यह कभी नहीं रहता है। लेकिन आप उसी चाल के साथ खेल सकते हैं set term tikz externalimagesऔर वह टर्मिनल हर "सेट टर्म" पर काउंटर को रीसेट करता है। आप set output "/dev/null"टिक्ज़ के साथ उपयोग नहीं कर सकते हैं , लेकिन अगर यह आपके लिए आउटपुट को दबाने का काम नहीं करता है तो आप परवाह नहीं कर सकते हैं। Tkcanvas और svg टर्मिनलों अन्य संभावनाएं हैं, लेकिन उन में बाहरी पीएनजी तंत्र gnuplot संस्करण और संकलित विकल्पों पर निर्भर करता है।
एथन

यह महान काम करता है! तथ्य के बाद थोड़ा नाम बदलना आवश्यक है, लेकिन अंत में मुझे एक पिक्सेल-सटीक छवि फ़ाइल मिलती है, जैसे मैं देख रहा था। धन्यवाद!
HotDogCannon

3

Gnuplot का उपयोग न करें।

इसके बजाय, एक स्क्रिप्ट लिखें जो आपके डेटा को पढ़ती है और इसे पोर्टेबल अनिमैप प्रारूपों में से एक में परिवर्तित करती है । यहाँ पायथन में एक उदाहरण दिया गया है:

#!/usr/bin/env python3
import math
import struct

width = 400
height = 200
levels = 255

raw_datum_fmt = '=d' # native, binary double-precision float
raw_datum_size = struct.calcsize(raw_datum_fmt)

with open('T.dat', 'rb') as f:
    print("P2")
    print("{} {}".format(width, height))
    print("{}".format(levels))

    raw_data = f.read(width * height * raw_datum_size)

    for y in range(height):
        for x in range(width):
            raw_datum, = struct.unpack_from(raw_datum_fmt, raw_data, (y * width + x) * raw_datum_size)
            datum = math.floor(raw_datum * levels) # assume a number in the range [0, 1]
            print("{:>3} ".format(datum), end='')
        print()

यदि आप डेटा फ़ाइल बनाने वाले प्रोग्राम को संशोधित कर सकते हैं, तो आप उपरोक्त चरण को छोड़ भी सकते हैं और इसके बजाय सीधे पीएनएम प्रारूप में डेटा उत्पन्न कर सकते हैं।

किसी भी तरह से, आप छवि को अपनी पसंद के प्रारूप में बदलने के लिए ImageMagick का उपयोग कर सकते हैं:

./convert.py | convert - pic.png

1
वास्तव में इस तरह के कार्य के लिए Gnuplot का उपयोग किसी चीज में कील चलाने के लिए एक पुस्तक का उपयोग करने जैसा है। यह काम कर सकता है लेकिन इस कार्य के लिए किताबें नहीं बनाई गई हैं। मेरा पसंदीदा उपकरण "GNU" डोमेन में बने रहने के लिए GNU ऑक्टेव होगा : इस imwriteफ़ंक्शन का उपयोग PNG छवि के रूप में 2D डेटा को बचाने के लिए किया जा सकता है।
4:00

यह एक दिलचस्प मार्ग है, और निश्चित रूप से एक मूल्यवान बैकअप है, लेकिन अगर मैं उपयोग नहीं करने जा रहा हूं gnuplot, तो मैं matplotlibइसके बजाय उपयोग करूंगा (नीचे मेरा उत्तर देखें)। यह एक महान योगदान है, लेकिन तकनीकी रूप से प्रश्न / इनाम एक gnuplotसमाधान के लिए पूछता है , क्योंकि यह इस विशेष कार्य के लिए प्रतीत होता है।
हॉटडॉगकैनन

3

यह एक आसान काम होना चाहिए, हालांकि, जाहिर तौर पर ऐसा नहीं है। निम्नलिखित एक (बोझिल) समाधान हो सकता है क्योंकि अन्य सभी प्रयास विफल रहे। मेरा संदेह यह है कि कुछ ग्राफिक्स लाइब्रेरी में एक समस्या है जिसे आप शायद gnuplot उपयोगकर्ता के रूप में हल नहीं कर सकते हैं।

आपने बताया कि ASCII मैट्रिक्स डेटा भी ठीक है। यहां "ट्रिक" डेटा को प्लॉट करने के लिए है with linesजहां डेटा को खाली लाइनों द्वारा "बाधित" किया जाता है, मूल रूप से एकल अंक खींचते हैं। यदि आपको अपने डेटाफ़ाइल 1: 1 को डेटब्लॉक में लाने की आवश्यकता है, तो इसे जांचें

हालांकि, अगर यह पहले से ही अजीब पर्याप्त नहीं है, इसके लिए काम करने लगता है pngऔर gifटर्मिनल लेकिन के लिए नहीं pngcairoया wxt। मुझे लगता है कि वर्कअराउंड शायद धीमा और अक्षम है, लेकिन कम से कम यह वांछित आउटपुट बनाता है। अगर आकार की कोई सीमा है तो मुझे यकीन नहीं है। Win7 के साथ 100x100 पिक्सल के साथ परीक्षण किया गया, gnuplot 5.2.6। टिप्पणियाँ और सुधार का स्वागत करते हैं।

कोड:

### pixel image from matrix data without strange white border
reset session

SizeX = 100
SizeY = 100
set terminal png size SizeX,SizeY
set output "tbPixelImage.png"

# generate some random matrix data
set print $Data2
    do for [y=1:SizeY] {
        Line = ''
        do for [x=1:SizeX] {
            Line = Line.sprintf(" %9d",int(rand(0)*0x01000000))  # random color
        }
        print Line
    }
set print
# print $Data2

# convert matrix data into x y z data with empty lines inbetween
set print $Data3
    do for [y=1:SizeY] {
        do for [x=1:SizeX] {
            print sprintf("%g %g %s", x, y, word($Data2[y],x))
            print ""
        }
    }
set print
# print $Data3

set margins 0,0,0,0
unset colorbox
unset border
unset key
unset tics

set xrange[1:SizeX]
set yrange[1:SizeY]

plot $Data3 u 1:2:3 w l lw 1 lc rgb var notitle

set output
### end of code

परिणाम: (100x100 पिक्सेल)

यहां छवि विवरण दर्ज करें

(काली पृष्ठभूमि के साथ बढ़े हुए):

यहां छवि विवरण दर्ज करें

400x200 पिक्सेल वाली छवि (मेरे 8 साल पुराने लैपटॉप पर 22 सेकंड लगते हैं)।

यहां छवि विवरण दर्ज करें


और क्या होगा अगर SizeX और SizeY बराबर नहीं हैं?
HotDogCannon

क्षमा करें, मैं मिला xऔर y। यह अभी भी काम कर रहा है SizeXऔर अगर SizeYनहीं के बराबर हैं। मैं कोड सही कर दूंगा।
Theozh

ठीक है, दिलचस्प दृष्टिकोण, लेकिन मैं पहली बार फ़ोर्टन से बाइनरी डेटा को एक सरणी या आपके जैसे स्ट्रीम में कैसे पढ़ूं Data2?
HotDogCannon

क्या आप किसी तरह 400x200 बाइनरी फ़ाइल को परीक्षण के लिए फ्लोटिंग पॉइंट डेटा प्रदान कर सकते हैं?
Theozh

1

प्रश्न / बाउंटी द्वारा gnuplotहल के लिए पूछे जाने पर भी मुझे जो कुछ भी चाहिए था, उसे प्राप्त करने के लिए मैंने वास्तव में उपयोग करके समाप्त कर लिया :

matplotlibएक फ़ंक्शन matplotlib.pyplot.imsave करता है जो मैं देख रहा था ... यानी 'बस डेटा पिक्सल' की साजिश रच रहा है और सीमाओं, मार्जिन, कुल्हाड़ियों, आदि की तरह कोई एक्स्ट्रा कलाकार नहीं है। मूल रूप से मैं केवल matplotlibbotot.imshow के बारे में जानता था और था छवि फ़ाइल से सभी एक्स्ट्रा को खत्म करने और किसी भी प्रक्षेप / चौरसाई आदि (और इसलिए gnuplotएक निश्चित बिंदु पर बदल गया) को रोकने के लिए बहुत सारी तरकीबें खींचो । साथ imsaveयह काफी आसान है, इसलिए मैं का उपयोग करके वापस कर रहा हूँ matplotlibएक के लिए आसान अभी तक 'सटीक पिक्सेल' भूखंडों के लिए अभी भी लचीला समाधान (रंग मैप, स्केलिंग, आदि के संदर्भ में)। यहाँ एक उदाहरण है:

#!/usr/bin/env python3

import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

nx = 400
ny = 200

data = np.fromfile('T.dat', dtype=np.float32, count=nx*ny)
data = data.reshape((nx,ny), order='F')
matplotlib.image.imsave('T.png', np.transpose(data), origin='lower', format='png')

1

ठीक है, यहां एक और संभावित समाधान है (मैंने इसे अपने पहले बोझिल दृष्टिकोण से अलग कर दिया)। यह भूखंड को तुरंत बनाता है, एक सेकंड से भी कम। बेकार फ़ाइल का आवश्यक नामकरण या निर्माण नहीं।

मुझे लगता है कि कुंजी का उपयोग करना है term pngऔर ps 0.1

मेरे पास कोई सबूत नहीं है, लेकिन मुझे लगता है ps 1कि सीए होगा। 6 पिक्सेल बड़े और कोने में कुछ ओवरलैप और / या सफेद पिक्सेल बनाएंगे। फिर, जिस भी कारण से यह काम करने लगता है, term pngलेकिन इसके साथ नहीं term pngcairo

मैंने क्या परीक्षण किया (Win7, gnuplot 5.2.6) एक द्विआधारी फ़ाइल है जिसमें पैटर्न 00 00 FFसभी पर दोहराया जाता है (मैं यहां नल बाइट्स प्रदर्शित नहीं कर सकता)। चूंकि gnuplot जाहिरा तौर पर 4 बाइट्स प्रति सरणी आइटम ( format="%d") पढ़ता है , यह एक आरजीबी पैटर्न की ओर जाता है अगर मैं साजिश रच रहा हूं with lc rgb var

उसी तरह (उम्मीद है) हम यह पता लगा सकते हैं कि format="%f"एक रंग पैलेट के साथ इसे कैसे पढ़ें और इसका उपयोग करें। मुझे लगता है कि तुम क्या देख रहे हो, है ना? आगे के परीक्षा परिणाम, टिप्पणियाँ, सुधार और स्पष्टीकरण स्वागत योग्य हैं।

कोड:

### pixel image from matrix data without strange white border
reset session

SizeX = 400
SizeY = 200
set terminal png size SizeX,SizeY
set output "tbPixelImage.png"

set margins 0,0,0,0
unset colorbox
unset border
unset key
unset tics

set xrange[0:SizeX-1]
set yrange[0:SizeY-1]

plot "tbBinary.dat" binary array=(SizeX,SizeY) format="%d" w p pt 5 ps 0.1 lc rgb var
### end of code

परिणाम:

यहां छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.