0

基本的に、画像内のボックス (関心領域) を選択し、ImageMagick の形式でジオメトリ出力を取得する簡単な方法が必要です。デフォルトの ImageMagick ビューアで簡単に実行する方法が見つからないdisplayので、独自のビューアをコーディングできるようにするための API (およびできればサンプル) を探しています。

ちょっとした背景: ImageMagick では • View topic - コマンド ラインから関心領域を選択する(2008) ことはできないと言われていますが、次のような表示があります: ImageMagick - 関心領域(2003?) では、その方法を説明しています。それ(しかし、どうやらそれは古いバージョンを指しているようです)。

とにかく、これはあなたが呼び出す方法ですdisplay -size 300x500 pattern:checkerboardpattern:checkerboardimagemagick の組み込みパターン画像です):

imagemagick 表示 ROI

「ImageMagick」表示ウィンドウが表示されたら、それをクリックします。次に、コマンド メニューが表示されます - そこから、/"Image Edit"/"Region of Interest..." を選択します。次に、ビューアの表示ウィンドウをクリックしてドラッグできます。また、左上隅にジオメトリも表示されますが、テキストとしてコピー/貼り付けすることはできません (そのため、再入力する必要がありました)。

また、displayコマンドラインモードでは端末を占有します(linux - 端末でimagemagickをdisplay終了させ、ウィンドウを保持します(シングルインスタンスモード)-スーパーユーザー)-「シングルインスタンスモード」で強制的に実行する方法がわかりません。コマンドラインでファイル名を発行し、display現在実行中の同じインスタンスにそれらをロードできるようにしました。

さて、私はImageMagick で呪文を唱える - プログラマーのための画像操作(2012) を見つけました。ここでは MagickWand API について言及しています。いくつか検索した後、imagemagickサイトで見つけました:

それで、私が最初に考えたのは Python のスクリプトでしたが、どうやら Perl API しかないようで、これで問題ありません。

ただし、コーディングする必要があるのは、基本的にコマンド ライン インターフェイスです。これはdisplay、「単一インスタンス」としてのようなウィンドウ プロセスを開始し、ファイル名などのパラメータを-densityウィンドウに渡しながらターミナルを終了します。ウィンドウはマウス クリックに反応し、トリミング ジオメトリ ボックス (対象領域) を選択できるようになります。最後に、ジオメトリ文字列をテキスト ボックスにレンダリングして、コピーできるようにします。しかし、私が見る限り、すべての API は command-line の機能を実行することを目的としていますconvert

だから私の質問は - これらの API のいずれかを使用して のdisplayような GUIをプログラムすることはできますか? 指摘できる同様の性質の例はありますか(できればスクリプト言語ですが、私はC / C ++で生きます)?

ご回答ありがとうございます。
乾杯!

4

1 に答える 1

4

まあ、これは少し面倒であることが判明しましたが、私が望んでいたように動作する ImageMagick API を使用して Perl-Tk スクリプトをまとめることができました: imgckdis.pl (コードも下にあります)。スクリーンショットは次のとおりです。

imgckdispl.png

ハードコードされた 400x400 ピクセルで画像を表示できることに注意してください (ただし、より大きな画像には拡張される可能性があります) - メニューもマウス操作 (スクロールホイールのズーム) もありません - ほとんど何もありません :) スクリプトは 1 つのコマンドラインしか受け入れません引数 - 開くファイル。ただし、「xc:white」などの ImageMagick スペシャルも理解できます (スクリーンショットに示すように、ImageMagick 部分は SVG ファイルを自動的にレンダリングします)。

しかし、できることの 1 つは、シングル インスタンス モードで動作することです。開始された最初のインスタンスが「マスター」になり、Tk ウィンドウを描画し、それぞれの端末をロックします。スクリプトの後続のインスタンスは、マスター インスタンスが既に開始されていることを認識すると、新しいイメージをロードするコマンドをマスターに発行するだけです。

この「'master' にコマンドを発行する」ことは、以下のリンク集 (およびオンラインvesrionのリビジョン ノート) が示すように、それほど簡単ではないことが判明しました。最初は、プロセス間通信共有変数を使用すると、マスターへの「参照によるポインター」を保存できると思いました。その後、後続のインスタンスがその関数を呼び出すことができるようにします。まあ、それはできないようです - 1つには、Perlはそれを思いとどまらせるかもしれません- しかし、これらのチェックをすべて飛び越えたとしても、最終的には共有空間とは見なされないメモリアドレスを取得するため、何も取得できませんそれから。さらに、IPC::ShareablePerl パッケージは、整数と文字列に対してのみ「保証」されている可能性があります?!

それにもかかわらず、最終的に機能したアプローチは、示唆されているように、変更された変数の変更を「マスター」にポーリングさせることです。非マスターインスタンスは、呼び出されたときにこの変数を単純に変更します-そして、このアプローチはうまくいくようです...しかし、「実際の」アプリケーションの場合、これらの共有変数のかなりの数を整理することを考える必要があります..

まあ、おそらくまだ画像をズームしたり再配置したり、ジオメトリの長方形を描いたりすることはできませんが、少なくとも(少なくともUbuntuでは)動作していることを実証できる例:)です...

これが誰かに役立つことを願っています、
乾杯!

コード:

#!/usr/bin/perl

# imgckdis.pl
# http://sdaaubckp.svn.sf.net/viewvc/sdaaubckp/single-scripts/imgckdis.pl

use warnings;
use strict;
use Image::Magick; # sudo apt-get install perlmagick # debian/ubuntu
use Tk;
use MIME::Base64;

use Carp;
use Fcntl ':flock';

use Data::Printer;
use Class::Inspector;

use IPC::Shareable;


my $amMaster = 1;
my $file_read;

open my $self, '<', $0 or die "Couldn't open self: $!";
flock $self, LOCK_EX | LOCK_NB or $amMaster = 0;

if ($amMaster == 1) {
  print "We are master single instance as per flock\n";
  IPC::Shareable->clean_up_all;
}

if (!$ARGV[0]) {
  $file_read = "xc:white";
} else {
  $file_read = $ARGV[0];
}
chomp $file_read;


my %options = (
  create    => 1,
  exclusive => 0,
  mode      => 0644,
  destroy   => 0,
);

my $glue1 = 'dat1';
my $glue2 = 'dat2';

my $refcount;
my $reffname;
my $lastreffname;

my $refcount_handle = tie $refcount, 'IPC::Shareable', $glue1 , \%options ;
if ($amMaster == 1) {
  $refcount = undef;
}

my $reffname_handle = tie $reffname, 'IPC::Shareable', $glue2 , \%options ;
if ($amMaster == 1) {
  $reffname = undef;
}

my ($image, $blob, $content, $tkimage, $mw);


if ($amMaster == 1) { # if (not(defined($refcount))) {
  # initialize the assigns
  $lastreffname = "";

  $reffname_handle->shlock(LOCK_SH|LOCK_NB);
  $reffname = $file_read; #
  $reffname_handle->shunlock();

  $refcount_handle->shlock(LOCK_SH|LOCK_NB);
  $refcount = 1; #
  $refcount_handle->shunlock();
}

# mainly from http://objectmix.com/perl/771215-how-display-image-magick-image-tk-canvas.html
sub generateImageContent() {
  #fake a PGM then convert it to gif
  $image = Image::Magick->new(
    size => "400x400",
  );
  $image->Read($file_read); #("xc:white");
  $image->Draw(
    primitive => 'line',
    points => "300,100 300,500",
    stroke => '#600',
  );
  # set it as PGM
  $image->Set(magick=>'pgm');

  #your pgm is loaded here, now change it to gif or whatever
  $image->Set(magick=>'gif');
  $blob = $image->ImageToBlob();

  # Tk wants base64encoded images
  $content = encode_base64( $blob ) or die $!;
}

sub loadImageContent() {
  #fake a PGM then convert it to gif
  $image = Image::Magick->new(
    size => "400x400",
  );
  $image->Read($lastreffname); #("xc:red") for test

  # set it as PGM
  $image->Set(magick=>'pgm');

  #your pgm is loaded here, now change it to gif or whatever
  $image->Set(magick=>'gif');
  $blob = $image->ImageToBlob();

  # Tk wants base64encoded images
  $content = encode_base64( $blob ) or die $!;

  #~ $tkimage->read($content); # expects filename
  $tkimage->put($content); # works!
}


sub CleanupExit() {
  # only one remove() passes - the second fails: "Couldn't remove shared memory segment/semaphore set"
  (tied $refcount)->remove();
  IPC::Shareable->clean_up;
  $mw->destroy();
  print "Exiting appliction!\n";
  exit;
}

sub updateVars() {
  if ( not($reffname eq $lastreffname) ) {
    print "Change: ", $lastreffname, " -> ", $reffname, "\n";
    $lastreffname = $reffname;
    loadImageContent();
  }
}

if ( not($amMaster == 1) ) {
  # simply set the shared variable to cmdarg variable
  # (master's updateVars should take care of update)
  $reffname_handle->shlock(LOCK_SH|LOCK_NB);
  $reffname = $file_read;
  $reffname_handle->shunlock();

  # and exit now - we don't want a second instance
  print "Main instance of this script is already running\n";
  croak "Loading new file: $file_read";
}


$mw = MainWindow->new();
$mw->protocol(WM_DELETE_WINDOW => sub { CleanupExit(); } );

generateImageContent();
$tkimage = $mw->Photo(-data => $content);

$mw->Label(-image => $tkimage)->pack(-expand => 1, -fill => 'both');
$mw->Button(-text => 'Quit', -command => sub { CleanupExit(); } )->pack;

# polling function for sharable - 100 ms
$mw->repeat(100, \&updateVars);


MainLoop;



__END__

関連リンク:

于 2012-05-20T01:12:07.793 に答える