gnuplot:マージンなしでピクセルごとに1つの2D配列要素をプロットする方法


9

gnuplot 5.0を使用して、マージンや境界線や軸のないデータの2D配列をプロットしようとしています...いくつかのデータを表す2D画像(.pngまたは.jpg)だけです。私がしたい画像に正確に1つの画素に対応するように各アレイ素子を用いてスケーリング/補間ないなどと縁で余分な白画素。

これまでのところ、マージンを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端末は、画像を含む個別の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画像として保存できます。
ブロンティン

これは興味深いルートであり、間違いなく貴重なバックアップですが、を使用しない場合は、代わりにgnuplot使用しmatplotlibます(以下の私の回答を参照)。これは大きな貢献ですが、技術的にはgnuplot、この特定のタスクには不向きであるように、質問/バウンティは解決策を求めます。
HotDogCannon

3

これは簡単な作業ですが、そうではないようです。他のすべての試みが失敗したため、以下は(面倒な)解決策になる可能性があります。私の疑いは、一部のグラフィックスライブラリにはgnuplotユーザーとして解決できない問題があるということです。

あなたはASCII行列データも大丈夫だと述べました。ここでの「トリック」とはwith lines、データが空の線で「中断」されている場所にデータをプロットし、基本的に単一の点を描くことです。データファイルをデータブロックに1:1で取得する必要がある場合は、これを確認してください。

しかし、それがまだ十分に奇妙ではない場合、それはpngand gif端末では機能するようですが、pngcairoor では機能しないようですwxt。回避策はおそらく遅くて非効率的ですが、少なくとも望ましい出力が作成されると思います。サイズに制限があるかわかりません。Win7、gnuplot 5.2.6で100x100ピクセルでテストされています。コメントや改善は大歓迎です。

コード:

### 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。それはまだ働いている場合SizeXSizeY同じではありません。コードを修正します。
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

さて、ここに別の可能な解決策があります(私はそれを私の最初の面倒なアプローチから分離しました)。1秒未満ですぐにプロットが作成されます。名前の変更や不要なファイルの作成は不要です。

私はキーが使用する推測term pngしてps 0.1

私には証拠はありませんが、ps 1およそだと思います。6ピクセルの大きさで、一部が重なり合うか、コーナーに白いピクセルが作成されます。繰り返しになりますが、何らかの理由で、で機能するように見えますが、では機能しterm pngないようterm pngcairoです。

私がテストしたもの(Win7、gnuplot 5.2.6)は、パターン00 00 FFがすべて繰り返されたバイナリファイルです(ここではnullバイトを表示できません)。gnuplotはformat="%d"、配列項目()ごとに4バイトを読み取るため、プロットしてwith lc rgb varいる場合、これによりRGBパターンが交互になります。

同じ方法で(うまくいけば)読み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.