gnuplot : 여백없이 픽셀 당 하나의 2D 배열 요소를 그리는 방법


9

gnuplot 5.0을 사용하여 여백이나 경계 또는 축이없는 2D 데이터 배열을 플로팅하려고합니다. 일부 데이터를 나타내는 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 터미널은 이미지가 포함 된 별도의 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 버전 및 컴파일 옵션에 따라 다릅니다.
Ethan

이것은 잘 작동합니다! 사실 이후 약간의 이름 변경이 필요하지만 결국 내가 찾던 것과 같은 픽셀 정확한 이미지 파일을 얻습니다. 감사!
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은 데이터가 빈 선으로 "중단 된"데이터 를 플로팅 하여 기본적으로 단일 점을 그리는 것입니다. datafile 1 : 1을 datablock으로 가져와야 할 경우이를 확인하십시오 .

이미 이상한 충분하지 않은 경우, 그것은을 위해 작동하는 것 같다 pnggif터미널하지만하지 않는 pngcairowxt. 해결 방법이 느리고 비효율적이지만 적어도 원하는 출력을 생성한다고 생각합니다. 크기에 제한이 있는지 확실하지 않습니다. 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 I가 ... 즉, 플로팅 그냥 데이터 픽셀 '을 찾고 있었다 등 테두리, 여백, 축, 같은 더 엑스트라가 원래 난 단지에 대해 알지도 무엇을하지 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 1ca 일 것이라고 생각 합니다. 6 픽셀이 크고 모서리에 겹치거나 흰색 픽셀이 생깁니다. 다시 말하지만 어떤 이유로 든 작동 term png하지만 작동 하지 않는 것 같습니다 term pngcairo.

내가 테스트 한 것은 (Win7, gnuplot 5.2.6) 패턴이 00 00 FF완전히 반복 되는 이진 파일입니다 (여기서는 null 바이트를 표시 할 수 없습니다). gnuplot은 배열 항목 ( format="%d") 당 4 바이트를 분명히 읽으므로 플로팅하면 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.