コンテンツへスキップ

関連記事:東芝REGZAのWEB API

PythonでのDigest認証

import requests
from requests.auth import HTTPDigestAuth
r = requests.get('http://@URL@', auth=HTTPDigestAuth('@user@', '@pass@'))
r.status_code

東芝テレビ(レグザ:REGZA)のWEB API仕様

WEB API実行時にDigest認証ダイジェストにんしょう)が必要となります。
ユーザ名およびパスワードは、レグザAppコネクト設定で設定したユーザー名とパスワードになります。

「(リモコン)設定ボタン」「接続機器設定」「外部連携設定」「レグザAppコネクト設定」

プログラムからの利用時には、Digest認証に対応した方法で利用する必要があります。

http://[REGZA IP]/remote/remote.htm?key=[command_key]

IE、Chrome、Firefoxなど一般ブラウザから動作確認できます。
戻り値は、テキスト出力として数字が返ってきました。
「0」成功 「0以外」失敗。
ブラウザで操作している際に、テレビの音量を上げようとすると「4」というエラー番号も見ることが出来ました。電源ボタンを押した直後に音量操作実施のタイミング。

テレビのIPアドレスが192.168.0.77の場合のコマンドサンプル

  • 音量を上げたいとき
    http://192.168.0.77/remote/remote.htm?key=40BF1A
  • チャンネル「8」ボタンを押す
    http://192.168.0.77/remote/remote.htm?key=40BF08
  • リモコンの「青」ボタンを押す
    http://192.168.0.77/remote/remote.htm?key=40BF73

[command_key]リスト

ボタン名[command_key]
140BF01
240BF02
340BF03
440BF04
540BF05
640BF06
740BF07
840BF08
940BF09
1040BF0A
1140BF0B
1240BF0C
入力切替40BF0F
消音40BF10
電源40BF12
音声切り替え40BF13
音量↑40BF1A
チャンネル↑40BF1B
画面表示40BF1C
音量↓40BF1E
チャンネル↓40BF1F
ブロードバンド40BF25
クイック40BF27
マルチ画面40BF29
画面サイズ40BF2B
戻る40BF3B
終了40BF3C
決定40BF3D
40BF3E
40BF3F
一時停止(静止)40BF50
40BF5B
40BF5F
CH番号40BF60
サーチ40BF60
ラジオ/データ40BF6D
番組表40BF6E
番組説明40BF71
40BF73
40BF74
40BF75
40BF76
ミニ番組表40BF77
地デジ40BF7A
地アナ40BF7B
BS40BF7C
CS40BF7D
録画40BF86
設定メニュー40BFD0
↑↑40BE20
↓↓40BE21
→→(30秒送り)40BE22
←←(10秒戻し)40BE23
早送りスキップ40BE26
戻るスキップ40BE27
録画リスト40BE28
停止40BE2B
巻き戻し40BE2C
再生40BE2D
早送り40BE2E
レグザメニュー40BE34
タイムシフト40BE35
番組検索40BE36
始めにジャンプ40BE47
イジェクト40BE93
ディスク40BE9E
dデータ43BC14
字幕43BC52

PythonでのREGZA操作サンプルソースコード

import requests
from requests.auth import HTTPDigestAuth

TV_IP = "xxx.xxx.xxx.xxx"
TV_USER = "user"
TV_PASS = "pass"
TV_VOLUME_DOWN = "40BF1E"
TV_BOTTON_8 = "40BF08"

def execjanken(key):
    url = "http://" + TV_IP + "/remote/remote.htm?key=" + key
    r = requests.get(url, auth=HTTPDigestAuth(TV_USER, TV_PASS))
    return True

//Change channel to 8
execjanken(TV_BOTTON_8)

画像検出率と処理フローで安定稼働(稼働1カ月)

2019年7月29日より稼働し、5週間。合計110回のめざましじゃんけん結果を蓄積しました。(平日25日×4回+土曜5日×2回)
最終週は、処理変更なしに、めざましテレビのめざましじゃんけん生放送中のリアルタイム画像検出を100%稼働させました。
一度しかない生放送、何気なく選んだテーマですが、ぞんぶんに楽しめる開発対象です。
機械学習部分に記事が追い付いてないのですが、現在Darknet / Tiny YOLO3を用いた画像検出を行っております。試行錯誤しておりますが、誤検出は存在してしまいます。
現在は、めざましじゃんけんの生放送に合わせた処理手順と画像検出を合わせて、画像の検出ミス時にも対応可能なシステムとしております。

画像検出と処理フロー

天気予報の晴れマークや気温の羅列、何かしらのテロップやフリップボードなど、予期せぬところで、Janken_Gooとじゃんけんでグーを出したと誤認識されることなどもあります。当初2次元であり難易度は低いと考えておりましたが、実写の報道番組という特性があり、出てくる画像パターンは多岐にわたりました。

現在のめざましじゃんけん画像検出システムは、誤検出が出たとしても、確率的に誤判定が出ないような処理フローとなっております。

Stage0:めざましじゃんけん開始前
Stage1:めざましじゃんけん開始を検出した状態(じゃんけんの手を選択する)
Stage2:出したじゃんけんの手を検出した状態(結果待ちの状態)
Stage3:めざましじゃんけん結果検出状態

めざましじゃんけん処理フロー

システムメインコンポーネント

Intel Neural Compute Stick 2

2019年08月26日週 めざましじゃんけん 結果

フジテレビ めざましテレビ めざましじゃんけん の結果を保証したり、全ての結果が記載を保証するものではありません。

2019年08月26日週 のめざましじゃんけんの結果を公開します。


じゃんけん結果システムイメージ

Goo(グー) Choki(チョキ) Pa(パー)

めざましテレビ|めざましじゃんけんーフジテレビ

めざましじゃんけん結果
回次結果対戦相手
8月31日
(土曜日)
【2戦目】08時21分松岡昌宏さん
【1戦目】07時22分ニック・ファジーカス選手
8月30日
(金曜日)
【4戦目】07時58分田中大貴 選手
【3戦目】07時35分加藤浩次さん
【2戦目】06時58分国分太一さん
【1戦目】05時58分まちかどじゃんけん
8月29日
(木曜日)
【4戦目】07時58分城島茂さん
【3戦目】07時35分松尾龍さん、中村浩大さん
【2戦目】06時58分岸井ゆきのさん
【1戦目】05時58分まちかどじゃんけん
8月28日
(水曜日)
【4戦目】07時58分生じゃんけん!ももいろクローバーZ
【3戦目】07時35分藤本美貴さん
【2戦目】06時58分サンドウィッチマン
【1戦目】05時58分まちかどじゃんけん
8月27日
(火曜日)
【4戦目】07時58分生じゃんけん!梶裕貴さん
【3戦目】07時35分比嘉愛未さん
【2戦目】06時58分生じゃんけん!酒井唯菜さん(2020ミス・ティーン・ジャパン)
【1戦目】05時58分まちかどじゃんけん
8月26日
(月曜日)
【4戦目】07時58分宮野真守さん、梶裕貴さん
【3戦目】07時35分山﨑賢人さん、新田真剣佑さん、永野芽郁さん
【2戦目】06時58分森本慎太郎さん
【1戦目】05時58分まちかどじゃんけん

ASRock の DeskMini 310 Series

少し前に、Shuttleの2.5インチドライブを4つ搭載可能なベアボーンを紹介しましたが、 Intel® H310チップセット搭載で、2.5インチドライブを2つ搭載可能なベアボーンに魅力を感じております。
参考記事:RAID対応ShuttleベアボーンXH270

メインサーバー Synology

  • 動作がもっさりすることがある
  • 特に、一番しっかりしてほしいWEBサーバーの動きがもっさり
    WEB APIのタイムアウトやWEBサイトへのアクセス不通

WordPressおよびDB(SQL)向けサーバを準備したいなと考えております。
よって、大容量が必要なNASはSynology。
CPU処理速度と十分なメモリ容量、そして少ない電力と考えていると今回のASRockのDeskMini 310 SeriesのASRock Intel H310ベアボーンが出てきました。

  • Synology DiskStation DS218j 2ベイ
    • 1.3GHzデュアルコアCPU
    • 512MB DDR3メモリ搭載

ASRock Intel H310ベアボーン

Mini-STX 、ミニ・ソケット・テクノロジー・エクステンデッド(Mini Socket Technology Extended)(Mini-STX)フォームファクタにより Intel® LGA 1151 ソケットベースの Intel® プロセッサー対応、Intelのデスクトップ向けCPUを搭載できるので、費用対効果の良いCore™ i3 プロセッサーを利用できます。

  • Supports Intel® 9th/8th Core™ / Pentium® / Celeron® LGA1151 processors
  • 2 x SO-DIMM DDR4-2666MHz, Max. 32GB (non-ECC)
  • 3 つのビデオ出力: DisplayPort、HDMI、D-Sub
  • 1 x Ultra M.2 PCIe Gen3 x4 スロット
  • 2 x 2 x 2.5" HDD/SSD トレイ
  • 1 x M.2 (2230) Wi-Fi スロット
  • USB 3.1 Gen1 Type-C ポート
  • Micro SD カードリーダー
CPUとメモリは、RAID対応ShuttleベアボーンXH270で紹介した製品を選ぶとして、ディスクは、信頼性を上げたいので2.5インチHDDを選ぶと思います。4万円前後で購入可能と思います。
(ShuttleベアボーンXH270構成:トータルで7万円ぐらいでした)
  • INTEL インテル Core i3-9100F
  • Crucial [Micron製] DDR4 ノート用メモリー 8GB x2 
  • 東芝 2.5インチ 1TB MQ01ABD100 SATA✕2台

ASRock DeskMini 310/B/BB/JP Intel H310チップセット搭載 Mini-STXフォームファクタ採用ベアボーンPC
intel MM999J4X Core i3-9100F LGA1151(INT-BX80684I39100F)

もちろん、Synologyも簡単にサーバー運用が出来るので、おすすめです。

SYNOLOGY シノロジー DiskStation DS218j デュアルコアCPU搭載多機能パーソナルクラウド 2ベイNASキット DS218j[DS218J]

テレビの電源オンオフ

他のリモコン操作の家電も同様ですが、現在の状態把握が難しいです。NatureRemoで電源オンとスケジュールしていても、実際は、電源ボタンを押すのみで、電源が消えていれば、電源ボタン操作で電源がオンとなりますが、電源オン状態であれば、電源操作により電源オフ状態と期待通りになりません。

HDMI接続によるCEC(Consumer Electronics Control)

結構盲点でした、物理的にテレビに接続し、制御可能なデバイスが既に導入されていたとは。Raspberry PiのHDMI端子を活用し、テレビのON/OFF(STANDBY)変更操作となります。電源のON/OFF(STANDBY)状況を確認することも可能です。

HDMIのCEC(Consumer Electronics Control)は、機器間を制御するリンク機能となり、SONYだとブラビアリンク、東芝だとレグザリンク、パナソニックだとビエラリンク、SHARPだとAQUOSファミリンクとなります。

cec-utilsインストール

@raspberrypi:~ $ sudo apt-get update
@raspberrypi:~ $ sudo apt-get upgrade -y
@raspberrypi:~ $ sudo apt-get install cec-utils -y

Raspberry Piの電源起動時に、TVの入力が切り替わったり、TVの電源が入らないよいうに、boot/config.txthdmi_ignore_cec_init=1を追記します。

@raspberrypi:~ $ vi /boot/config.txt
@raspberrypi:~ $ sudo vi /boot/config.txt
@raspberrypi:~ $ tail /boot/config.txt
#dtoverlay=vc4-fkms-v3d

# NOOBS Auto-generated Settings:
hdmi_force_hotplug=1
start_x=1
gpu_mem=128

#add
hdmi_ignore_cec_init=1

cec-utilsコマンド実行

状態確認:sudo cec-client -l

HDMIケーブル未接続時

@raspberrypi:~ $ sudo cec-client -l
libCEC version: 4.0.4, compiled on Linux-4.15.0-48-generic ... , features: P8_USB, DRM, P8_detect, randr, RPi, Exynos, AOCEC
Found devices: NONE

HDMIケーブル接続時

@raspberrypi:~ $ sudo cec-client -l
libCEC version: 4.0.4, compiled on Linux-4.15.0-48-generic ... , features: P8_USB, DRM, P8_detect, randr, RPi, Exynos, AOCEC
Found devices: 1

device: 1
com port: RPI
vendor id: 2708
product id: 1001
firmware version: 1
type: Raspberry Pi

TV電源ON:echo 'on 0' | cec-client -s

アクセス権によりコマンド失敗

@raspberrypi:~ $ echo 'standby 0' | cec-client -s
* failed to open vchiq instance

アクセス権を変更変更

@raspberrypi:~ $ ls -al /dev/vchiq
crw-rw---- 1 root video 243, 0 8月 18 09:38 /dev/vchiq
@raspberrypi:~ $ sudo chmod 666 /dev/vchiq
@raspberrypi:~ $ ls -al /dev/vchiq
crw-rw-rw- 1 root video 243, 0 8月 18 09:38 /dev/vchiq

tvserviceが起動していてコマンド失敗

tvservice --offが必要

TV電源OFF:echo 'standby 0' | cec-client -s

PHPから実行

function tv_on_HDMI()
{
    exec("echo 'on 0' | cec-client -s -d", $output, $result);

    if ($result) {
        echo "echo 'on 0' | cec-client -s 成功", PHP_EOL;
    } else {
        echo "echo 'on 0' | cec-client -s 失敗", PHP_EOL;
        echo implode(PHP_EOL, $output);
	}
    return $result;
}

function tv_off_HDMI()
{
    exec("echo 'standby 0' | cec-client -s", $output, $result);

    if ($result) {
        echo "echo 'standby 0' | cec-client -s 成功", PHP_EOL;
    } else {
        echo "echo 'standby 0' | cec-client -s 失敗", PHP_EOL;
        echo implode(PHP_EOL, $output);
	}
    return $result;
}

tv_on_HDMI();
tv_off_HDMI();

参考にさせて頂いたサイト

Raspberry PiとテレビをHDMI接続してテレビのON/OFFを確認する

RaspberryPi コマンドでテレビ電源をオンオフする(cec制御)echo 'on 0' | cec-client -s

Neural Compute Stick 2 (NCS) による結果検出リアルタイム化V1.1システムアップデート

主な変更点

Raspberry PiにNeural Compute Stick 2を導入。

画像検出速度の飛躍的な向上を実現し、めざましじゃんけん放映時のテレビ画面を用いたリアルタイム画像認識を実現。じゃんけん結果認識直後に、TwitterおよびWEBページに結果を公開。
めざましじゃんけん結果公開までの時間(速さ)で、世界No1を実現。(本家テレビデータ放送を除くWEB分野、個人による調査結果)

  • じゃんけん終了とほぼ同時の結果速報通知(Raspberry Piでの画像検出実施)
    Raspberry Piで画面キャプチャし、Windowsのメインマシンでの画像検出というシーケンス処理からよりリアルタイムな画像検出を実施
  • 試行中じゃんけん出し手の予測エンジンをRaspberry Piで実行

上記より、めざましじゃんけん結果検出時のメインマシンWindows不要化を実現。
機械学習の学習モデル作成時は、GPUが必須であり、Windowsで実施。

V1.1機能一覧と実装(V1からの変更点)

機能名実装
画像検出フレームワーク準備学習データ収集Raspberry PiとWEBカメラで、めざましじゃんけん実施時の画面キャプチャー取得
学習データ整理メインのWindowsマシンで実施。
LabelImgで学習したい内容のラベル登録
学習メインのWindowsマシンでDarknetを用いて実施。
システム起動TV起動Raspberry PiよりNature Remo経由で実施。
→HDMI
TVチャネル変更Raspberry PiよりテレビREGZAのWEB APIを用いて実施。
じゃんけん時の「青」「赤」「緑」ボタン操作もRaspberry PiよりWEB APIを用いて実施。
メインマシン起動
処理削除
メインマシン(Windows)の起動をRaspberry Piより実施
画像検出画像蓄積Raspberry PiのWEBカメラを用いて目覚ましテレビの画像をキャプチャー
画像移動
処理削除
Raspberry PiでキャプチャーしたデータをWindowsのメインマインに移動
めざましじゃんけん開始検出Raspberry Piよりめざましテレビ放送中のじゃんけん開始を検知
じゃんけん参加Raspberry Piよりじゃんけん開始検知後にじゃんけん実施(「青」「赤」「緑」ボタン操作)
画像検出WindowsマシンRaspberry Piで画像検出を実施。
検出結果結果をDB登録WindowsマシンRaspberry Piより画像検出結果をSynology NASのSQL DBへ登録
情報発信WEBコンテンツSQL DB情報よりWEBコンテンツの更新。Synologyで実施。
Twitter発信WEBコンテンツ更新と同じタイミングでTwitter発信を実施。処理はSynologyで実施。
じゃんけん予測じゃんけん予測時系列予測RNNをtensorflow/kerasを用いて実装

システムの主要コンポーネント

Intel Neural Compute Stick 2
SYNOLOGY シノロジー DiskStation DS218j デュアルコアCPU搭載多機能パーソナルクラウド 2ベイNASキット DS218j[DS218J]

2019年08月19日週 めざましじゃんけん結果

個人の実験的な試行内容であり、めざましじゃんけんの結果を保証したり、全ての結果が記載を保証するものではありません。

2019年08月19日週 のめざましじゃんけんの結果をベストエフォートで公開します。

Goo(グー) Choki(チョキ) Pa(パー)

めざましテレビ|めざましじゃんけんーフジテレビ

めざましじゃんけん結果
回次結果対戦相手
8月24日
(土曜日)
【2戦目】08時21分丸山城志郎選手
【1戦目】07時22分飯尾和樹さん(ずん)
8月23日
(金曜日)
【4戦目】07時58分佐々木希さん
【3戦目】07時35分髙藤直寿 選手
【2戦目】06時58分ローラさん
【1戦目】05時58分まちかどじゃんけん
8月22日
(木曜日)
【4戦目】07時58分加藤諒さん
【3戦目】07時35分阿部詩選手
【2戦目】06時58分林蓮音さん、和田優希さん
【1戦目】05時58分まちかどじゃんけん
8月21日
(水曜日)
【4戦目】07時58分生じゃんけん!軽部真一アナウンサー
【3戦目】07時35分ウルフアロン選手
【2戦目】06時58分TAKAHIROさん 市原隼人さん 岡田義徳さん
【1戦目】05時58分まちかどじゃんけん
8月20日
(火曜日)
【4戦目】07時58分生じゃんけん!梶裕貴さん
【3戦目】07時35分朝比奈沙羅選手
【2戦目】06時58分高嶋政伸さん
【1戦目】05時58分まちかどじゃんけん
8月19日
(月曜日)
【4戦目】07時58分超特急
【3戦目】07時35分芳田司 選手
【2戦目】06時58分上野樹里さん
【1戦目】05時58分まちかどじゃんけん

SynologyのphpMyAdminセッションタイムアウト変更

phpMyAdminの設定ファイル「config.inc.php」を変更します。
具体的には、「config.inc.php」の最終行に、設定したいタイムアウト値を秒指定で登録します。
$cfg['LoginCookieValidity'] = 86400; //タイムアウト24時間と設定する場合

@Synology:~$ sudo vi /volume1/web/phpMyAdmin/config.inc.php
Password:
@Synology:~$ tail /volume1/web/phpMyAdmin/config.inc.php
* default = 'ask'
*/
//$cfg['SendErrorReports'] = 'always';

/**
* You can find more configuration options in the documentation
* in the doc/ folder or at <https://docs.phpmyadmin.net/>.
*/
$cfg['LoginCookieValidity'] = 86400; //24時間

画像検出に向けて利用するフレームワーク

本家のDarknetも利用しましたが、特定ケースでの学習失敗やメモリ操作関係の不具合など、私自身も上手く行かないケースも有り、ブログ記事などからもAlexeyABを勧めている内容が多かったので、早い時期よりAlexeyABを導入し利用しております。

AlexeyABのDarknetは、WindowsおよびLinuxのDarknet Yolo v3 & v2のNeural Networks for object detection (Tensor Cores are used)をサポートしております。

AlexeyAB公開サイト

以下、サイトにすべての利用方法が記載されております。関連ソフトのインストール方法や、独自学習の方法など。

Darknetインストール方法

本件も同様ですが、AlexeyABでも2つのインストール方法が紹介されております。
最終的には、Legacy wayのVisual StudioでコンパイルしたDarknetを利用しております。この投稿では、2番めのLegacy way(Visual Studio)を利用したコンパイル方法を紹介します。

  1. How to compile on Windows (using vcpkg)
  2. How to compile on Windows (legacy way)

GitHUBよりAlexeyAB一式をダウンロードしておきます。
今後の学習モデル作成時などにも利用するフォルダとなるので、それなりの容量の余裕などを考え、各種ファイルを配置して下さい。

Visual Studioを利用したDarknetの導入

CUDA、cuDNN、OpenCVを導入します。

CUDAとcuDNNインストール

NVIDIA cuDNNの入手には、開発コミュニティへの登録が必要であるが、 cuDNNは、機械学習時のGPU-accelerated libraryとなるので、開発者登録を行い、導入しているCUDAと同じバージョンのcuDNNを入手し、入手したファイルをCUDAインストールフォルダに配置しましょう。

OpenCV導入

https://opencv.org/releases/より必要なバージョンをダウンロードし、Windowsの環境変数Pathに「\opencv\build\bin」を追加します。

C:\opencv\bin;それまでの値

Visual Studioよりプロジェクトオープン

GitHUBよりダウンロードしたファイル群のbuild\darknet\darknet.slnをオープン。

コンパイル時のエラー対応

すでに複数バージョンのDarknetをインストールしましたが、何度か同じエラーが出ております。opencvのライブラリー不足です。
おそらく、コードに直接ライブラリ名が記載されております。エラー内容を見て、エラーが示すバージョンのOpencvをセットアップして、再度ビルドを事項して下さい。

重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー LNK1104 ファイル 'opencv_world343.lib' を開くことができません。 darknet S:\Public\Documents\Git\darknet\build\darknet\LINK 1

各種参考にさせて頂いたサイト

WordPress利用時のTwitterカード

「Wordpress」を利用している際は、「All in One SEO」プラグインを利用するとソーシャル設定が簡単に実施できます。Twitter向けにカードタイプの指定やカスタムTwitter画像設定も簡単に設定できます。

All in One SEOを導入し、各投稿画面の「ソーシャル設定」画面で、Twitterの関連箇所を設定します。

Twitterサービス上のTwitterカード情報の更新

Twitterで投稿をPOST時に、URLが記載されていると、Tweetの下部に記載したURLのイマージ画像やページサマリが表示されます。これが、Twitterカードとなります。
Twitterカードが適切に表示されると、テキストだけよりもインパクトがり、注目を集めやすいです。

Twitterカードで指定している画像の変更や、サマリ部分の文章を変更した際に、誤字脱字等のケースも有り、すぐに最新の情報に更新したい場合があります。
通常は、週次でキャッシュの更新処理を行っているようなので、しばらく時間を置けば最新の情報にTwitterカードは更新されるようです。

強制的にTwitterカードをリフレッシュするには、以下のリンク(Card Validator)より対象のURLのTwitterカードを手動で表示させ、内容を更新させて下さい。

画像ファイルを変更した際に、ファイル名・URLに変更がないと、キャッシュが更新されないケースもあるので、画像ファイルのファイル名に?xxx(myimage.jpg?4362984378)などと指定し、少し強引にファイルが変更したように設定変更を行い、Card validatorでプレビューの取得を実施して下さい。

有用な情報が多かったので、ヘルプページのリンクと内容も掲載しておきます。

Card validator

 

Optimize Tweets with Cards

Refreshing a Card in a Tweet

I updated my site meta tags, but my Tweet shows the old Card. How do I refresh the Card?

Our web crawlers re-index the Card tag information on your page roughly every week.

When testing and/or iterating on Cards, it is sometimes helpful to test updates on your timeline. It may be possible to use the following technique to refresh the cache with your most up-to-date changes of your page’s Card.

  1. Add Card metadata to a page
  2. Tweet URL to that page
  3. Refresh your browser to view the Card contents on your timeline
  4. Change Card metadata on the page
  5. Take the same URL and runs it through bit.ly
  6. Tweet the new bit.ly URL
  7. Refresh your browser to view the updates

Additionally, you can create multiple bit.ly URLs to allow for repeat testing. For example, adding dummy parameters to the end of your URL (http://www.test.com/?x=test1) or a unique hash (http://www.test.com/#test1) will generally not affect the page contents, but will generate a unique bit.ly URL for each unique value of x.

My Card information now refreshes, but images are not updating. How do I get the images to refresh?/a>

Images referenced in a Card are also cached based on URL. This often causes images to not update when the above Card refresh technique is used.

To work-around this issue, you can add an extra parameter at the end of your image URL so that the Twitterbot treats the image as a unique URL and re-fetches the image.

For example:

<meta name="twitter:image" content="http://example.com/myimage.jpg?4362984378"></meta>