gnuplot: วิธีพล็อตองค์ประกอบอาร์เรย์ 2 มิติต่อพิกเซลโดยไม่มีระยะขอบ


9

ฉันกำลังพยายามใช้ gnuplot 5.0 เพื่อพล็อตอาร์เรย์ข้อมูล 2 มิติโดยไม่มีระยะขอบหรือเส้นขอบหรือแกน ... เพียงแค่ภาพ 2D (.png หรือ. jpg) ที่แสดงถึงข้อมูลบางอย่าง ฉันต้องการให้แต่ละองค์ประกอบอาร์เรย์สอดคล้องกับหนึ่งพิกเซลในภาพโดยไม่มีการปรับขนาด / การแก้ไขฯลฯ และไม่มีพิกเซลสีขาวพิเศษที่ขอบ

จนถึงตอนนี้เมื่อฉันพยายามตั้งค่าระยะขอบเป็น 0 และแม้กระทั่งการใช้pixelsธงฉันยังคงมีพิกเซลสีขาวแถวหนึ่งอยู่ที่ขอบด้านขวาและขอบด้านบนของภาพ

ฉันจะได้รับเพียงแค่ไฟล์รูปภาพที่มีการแสดงพิกเซลต่อพิกเซลของอาเรย์ข้อมูลและไม่มีอะไรพิเศษได้อย่างไร

สคริปต์ gnuplot:

#!/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

ข้อมูลตัวอย่างจาก Fortran 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 บางตัวใช้ "with image" โดยสร้างไฟล์ png แยกต่างหากที่มีภาพและจากนั้นเชื่อมโยงไปยังพล็อตที่เกิดขึ้น การใช้ไฟล์ภาพ 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. หลีกเลี่ยงเอาต์พุตใน Windows, 2. ตั้งชื่อของฉันเองโดยไม่มีดัชนีไปยังไฟล์ png หรืออย่างน้อยหยุดเพิ่มดัชนีของไฟล์ png ทุกครั้งที่คุณสร้างพล็อต
theozh

ฉันไม่สามารถช่วยออก Windows คุณพูดถูกเกี่ยวกับตัวนับในเทอร์มินัลผ้าใบ มันไม่เคยรีเซ็ต แต่คุณสามารถเล่นเล่ห์เหลี่ยมเดียวกันได้set term tikz externalimagesและเทอร์มินัลนั้นจะรีเซ็ตตัวนับบน "คำศัพท์ที่กำหนด" ทุกตัว คุณไม่สามารถใช้set output "/dev/null"กับ tikz ได้ แต่หากวิธีนี้ไม่ได้ผลในการปราบปรามเอาต์พุตสำหรับคุณคุณอาจไม่สนใจ เทอร์มินัล tkcanvas และ svg นั้นมีความเป็นไปได้อื่น ๆ แต่กลไก png ภายนอกนั้นขึ้นอยู่กับรุ่น gnuplot และตัวเลือกการคอมไพล์
อีธาน

มันใช้งานได้ดี! จำเป็นต้องเปลี่ยนชื่อเล็กน้อยหลังจากความจริงแล้ว แต่ในที่สุดฉันก็ได้ไฟล์รูปภาพที่มีพิกเซลตรงตามที่ฉันต้องการ ขอบคุณ!
HotDogCannon

3

อย่าใช้ gnuplot

แต่เขียนสคริปต์ที่อ่านข้อมูลและแปลงของคุณเป็นหนึ่งในรูปแบบพกพา anymap นี่คือตัวอย่างใน Python:

#!/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()

หากคุณสามารถแก้ไขโปรแกรมที่สร้างไฟล์ข้อมูลคุณสามารถข้ามขั้นตอนข้างต้นและสร้างข้อมูลโดยตรงในรูปแบบ PNM แทน

ไม่ว่าจะด้วยวิธีใดคุณสามารถใช้ ImageMagick เพื่อแปลงรูปภาพเป็นรูปแบบที่คุณต้องการได้:

./convert.py | convert - pic.png

1
แน่นอนว่าการใช้ Gnuplot สำหรับงานประเภทนี้ก็เหมือนกับการใช้หนังสือเล่มหนึ่งเพื่อตอกตะปูให้เป็นอะไร อาจใช้ได้ แต่ไม่ได้ทำหนังสือสำหรับงานนี้ เครื่องมือที่ฉันต้องการคือGNU Octaveจะยังคงอยู่ในโดเมน "GNU" :) imwriteฟังก์ชั่นนี้สามารถใช้เพื่อบันทึกข้อมูล 2D เป็นภาพ PNG
blerontin

นี่เป็นเส้นทางที่น่าสนใจและเป็นการสำรองข้อมูลที่มีค่า แต่ถ้าฉันไม่ได้ใช้gnuplotฉันจะใช้matplotlibแทน (ดูคำตอบของฉันด้านล่าง) นี่เป็นผลงานที่ยอดเยี่ยม แต่ในทางเทคนิคแล้วคำถาม / เงินรางวัลขอให้มีgnuplotวิธีแก้ปัญหาที่ไม่เหมาะสำหรับงานนี้โดยเฉพาะ
HotDogCannon

3

นี่ควรจะเป็นงานง่าย แต่เห็นได้ชัดว่าไม่ใช่ ต่อไปนี้อาจเป็นโซลูชัน (ยุ่งยาก) เนื่องจากความพยายามอื่น ๆ ทั้งหมดล้มเหลว ความสงสัยของฉันคือห้องสมุดกราฟิกบางแห่งมีปัญหาซึ่งคุณอาจไม่สามารถแก้ไขได้ในฐานะผู้ใช้ gnuplot

คุณพูดถึงว่าข้อมูลเมทริกซ์ ASCII ก็โอเคเช่นกัน "เคล็ดลับ" ที่นี่คือการลงจุดข้อมูลwith linesที่ข้อมูลถูก "ขัดจังหวะ" โดยบรรทัดว่างโดยทั่วไปวาดจุดเดียว เลือกตัวเลือกนี้ในกรณีที่คุณต้องนำดาต้าไฟล์ของคุณ1: 1 ไปไว้ในฐานข้อมูล

แต่ถ้ามันไม่ได้แปลกพอมันดูเหมือนว่าจะทำงานpngและgifขั้ว แต่ไม่ได้หรือpngcairo wxtฉันเดาวิธีแก้ปัญหาอาจช้าและไม่มีประสิทธิภาพ แต่อย่างน้อยก็สร้างผลลัพธ์ที่ต้องการ ฉันไม่แน่ใจว่ามีข้อ จำกัด เรื่องขนาดหรือไม่ ทดสอบด้วย 100x100 พิกเซลด้วย Win7, 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 พิกเซล (ใช้เวลาประมาณ 22 วินาทีในแล็ปท็อปอายุ 8 ปีของฉัน)

ป้อนคำอธิบายรูปภาพที่นี่


และถ้าหาก SizeX และ SizeY ไม่เท่ากันล่ะ
HotDogCannon

ขอโทษฉันผสมขึ้นและx yมันยังคงทำงานถ้าSizeXและSizeYไม่เท่ากัน ฉันจะแก้ไขรหัส
theozh

ตกลงวิธีการที่น่าสนใจ แต่ฉันจะอ่านข้อมูลไบนารีจาก Fortran เป็นอาร์เรย์หรือสตรีมแบบของคุณได้Data2อย่างไร
HotDogCannon

คุณสามารถให้ไบนารี่ไฟล์ขนาด 400x200 กับข้อมูลทศนิยมเพื่อทดสอบได้หรือไม่?
theozh

1

สิ่งที่ฉันลงเอยด้วยการใช้จริงเพื่อให้ได้สิ่งที่ฉันต้องการแม้ว่าคำถาม / ค่าหัวจะขอgnuplotทางออก

matplotlibมีฟังก์ชั่นmatplotlib.pyplot.imsaveซึ่งทำในสิ่งที่ฉันกำลังมองหา ... เช่นการพล็อต 'เพียงแค่พิกเซลข้อมูล' และไม่มีสิ่งพิเศษเช่นเส้นขอบระยะขอบแกน ฯลฯ ในตอนแรกฉันรู้เพียงแค่เกี่ยวกับmatplotlib.pyplot.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 pngps 0.1

ฉันไม่มีหลักฐาน แต่ฉันคิดว่าps 1น่าจะเป็นแคลิฟอร์เนีย 6 พิกเซลที่มีขนาดใหญ่และจะสร้างพิกเซลที่ทับซ้อนกันและ / หรือสีขาวที่มุม อีกครั้งด้วยเหตุผลใดก็ดูเหมือนว่าจะทำงานร่วมกับแต่ไม่ได้มีterm pngterm pngcairo

สิ่งที่ฉันทดสอบ (Win7, gnuplot 5.2.6) เป็นไฟล์ไบนารีที่มีรูปแบบ00 00 FFซ้ำ ๆ กันหมด (ฉันไม่สามารถแสดงค่า null ที่นี่) ตั้งแต่ gnuplot เห็นได้ชัดอ่าน 4 ไบต์ต่อรายการ array ( format="%d") นำไปสู่การนี้เพื่อสลับรูปแบบ RGB 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

ผลลัพธ์:

ป้อนคำอธิบายรูปภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.