pyautogui as pag # デスクトップスクリーンを制御するモジュールを使って、得られた画像をTCP通信配信する作品の例です。
# MySrcTcpServer.py
import socket
import threading
import numpy as np
import cv2
import pyautogui as pag # デスクトップスクリーンを制御するモジュール
server_ip = "127.0.0.1"
server_port = 80
listen_num = 5
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print(type(tcp_server), "のソケットオブジェクトの作成")
tcp_server.bind((server_ip, server_port))
print("ソケットにIPアドレス:{}ポート:{}を紐づける".format(server_ip,server_port))
tcp_server.listen(listen_num)
print("listenで接続可能状態へ移行")
def rec_send(client,head,body): # 受信はしていません。head,bodyをclientのソケットで送信する関数です。
client.send(head) # 送信
lst=np.frombuffer( head , dtype="int16")#2バイト、リトルエンディアンで変換
print("-------------", lst)
client.send(body) # 送信
client.close()
while True:
img=pag.screenshot() # デスクトップ画面キャプチャ
img=np.asarray(img)
img=cv2.cvtColor(img,cv2.COLOR_RGB2BGR)
cv2.imwrite("scr.png", img) # 画像ファイル生成
print( img.shape ) # 例:(1080, 1920, 3)
a=np.array(img.shape, dtype="int16") # aに「array([1080, 1920, 3], dtype=int16)」がセット
head=b''.join( a ) # bytes型 設定例:b'8\x04\x80\x07\x03\x00'
size=img.shape[0]*img.shape[1]*img.shape[2] # 設定例:1080*1920の2073600が記憶
body=img.reshape(size,-1)
body=np.frombuffer( body , dtype="int16")#2バイト、リトルエンディアンで変換
#
client,address = tcp_server.accept()
print("クライアント接続許可:",type(client), address)
#
t_id = threading.Thread(target=rec_send, args=(client, head, body))
t_id.start()
上記を変更して作った作品です。
変更点1:上記はクライアント接続時にキャプチャしていますが、以下は1秒ごにキャプチャしてファイル化しています。
そして、クライアント接続時は、ファイルを送信しています。(接続が多い時に余計なキャプチャをさせないためです。)
ファイル("scr.jpg")は、ファイル全体をバイナリーイメージで送るだけにしました
変更点2:キースレッドで、強制終了やトリミング指定制御を追加しました。
# tcp_desktopserver.py
import pyautogui as pag # デスクトップスクリーンを制御するモジュール
import numpy as np
import cv2
import time
import shutil
import sys
import threading
import socket
host = socket.gethostname() # ホスト名を取得、表示
print("ホスト名:", host)
info = socket.gethostbyname_ex(host) # ipアドレスを取得、表示
print(type(info), ":", info)
s=input("使用するデバイスの添え字>") ; ip_idx=0 if s == "" else int(s)
server_ip = info[2][ip_idx]
s=input("ポート番号(defual:3000)>"); server_port = 3000 if s == "" else int(s)
print(f"使用するIPアドレス:ポート番号={ server_ip}:{server_port }")
listen_num = 20 # 接続クライアント数
# 1.ソケットオブジェクトの作成
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.作成したソケットオブジェクトにIPアドレスとポートを紐づける
tcp_server.bind((server_ip, server_port))
print("server : bind")
# 3.作成したオブジェクトを接続可能状態にする
tcp_server.listen(listen_num)
flag_Trimming = False # 画像をトリミングするか?のフラグ
def stop_start(): # スレッドでキー入力を行い、'Q'の入力で終了できるようにしている。('T'入力でトリミングの切り替え)
global flag_Trimming
while True:
s = input("")
print("Q ENTERのキー入力で終了:(T:トリミング)>>", end="")
if s == "T" : flag_Trimming = not flag_Trimming
if s == "Q" :
tcp_server.close()
print("強制終了しました。!!")
sys.exit()
t_id2 = threading.Thread(target=stop_start)
t_id2.start() # 上記キー入力スレッド起動
import time # 1秒ごとにキャプチャーする制御で使う
prve_time=0 # 繰り返しにおいて前のキャプチャー時間を記憶
count = 0 # キャプチャー回数のカウント
img = None # これにイメージがある時、接続クライアント送信する。
Quality = 20 # cv2でjpgファイル化する時のクオリティ指定
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), Quality]
while True:
n_time= time.time()#現在時間取得
if n_time - prve_time > 1.0: # 1秒ごとにキャプチャーする制御
prve_time = n_time
try:
img=pag.screenshot() # デスクトップキャプチャ
img=np.asarray(img)
img=cv2.cvtColor(img,cv2.COLOR_RGB2BGR)
h, w, ch = img.shape
w=1000 if w > 1000 else w
h=1000 if h > 1000 else h
if flag_Trimming : img=img[:h , :w ] # トリミング
filename = "scr.jpg"
result, encimg = cv2.imencode(".jpg", img, encode_param)
img=cv2.imdecode(encimg, cv2.IMREAD_UNCHANGED)
cv2.imwrite(filename, img) # jpgのファイル書き込み
print(type(img), end="のキャプチャから" )
f=open(filename,"rb")
img = f.read()
print(type(img) ,end=f"のメージ生成。トリミング:{flag_Trimming}\n" )
f.close()
count+=1
print(f"●キャプチャ回数:{count} サイズ:{len(img)} ++++++++++{server_ip}:{str(server_port)}")
except Exception as e:
print(e)
if not img : continue
print("server: wait for accept", end="")
client,address = tcp_server.accept()
print("[*] Connected!! [ Source : {}]".format(address))
# 7.クライアントへ送る
client.send(img)
# 8.接続を終了させる
client.close()
package getp;
// Java の最初に作られたGUIがawtで、そのTCP接続したサーバから受信した画像をCanvasに描画する繰り返しの作品
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import java.net.*;
import java.nio.ByteBuffer;
public class PaintImage extends Frame implements ActionListener, Runnable {
BufferedImage bufferedImage = new BufferedImage(800,800,BufferedImage.TYPE_INT_RGB);
int width, height;
Panel panel = new Panel();
Label labelIP= new Label("IP Address:");
TextField textFieldIP= new TextField("192.168.71.8");
Label labelPort= new Label(" Port No:");
TextField textFieldPort= new TextField("3000");
Button btnCtrl= new Button("START");
Label labelMsg= new Label("It is an application that receives and displays images.");
ScrollPane scrPane = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); //常にスクロールバー表示
Thread thread = null;
Canvas canvas = new Canvas(){
public void paint(Graphics graphics) {
graphics.drawImage(bufferedImage, 0, 0, null);//描画処理
}
};
public static void main(String [] args) throws Exception {
new PaintImage();
}
PaintImage() throws Exception {
super("PaintImage");
setLayout(new BorderLayout());
panel.add(labelIP);
panel.add(textFieldIP);
panel.add(labelPort);
panel.add(textFieldPort);
panel.add(btnCtrl);
add(panel,BorderLayout.NORTH);
scrPane.add(canvas);
add(scrPane,BorderLayout.CENTER);
add(labelMsg,BorderLayout.SOUTH);
loadTxt();
setSize(800, 800); setVisible(true);
btnCtrl.addActionListener(this);
this.addWindowListener( new WindowAdapter(){
public void windowClosing(WindowEvent e){// 閉じるボタンで
thread = null;
saveTxt();
PaintImage.this.dispose();//破棄して、終了させる。
}
});
}
void saveTxt(){
try {
FileOutputStream os=new FileOutputStream("getpaint.txt");
String s="IP:" + textFieldIP.getText() + "\r\n";
s += "PORT:" + textFieldPort.getText() + "\r\n";
os.write( s.getBytes() );
os.close();
} catch(Exception e){
}
}
static String getValue(String s,String key){
int i1 = s.indexOf(key);
int i2 = s.indexOf("\r\n", i1);
if(i1 == -1 || i2 == -1) return "";
return s.substring(i1+key.length(), i2);
}
void loadTxt(){
try {
File file = new File("getpaint.txt");
FileInputStream is=new FileInputStream(file);
byte []buf = new byte[(int) file.length()];
is.read(buf);
String s = new String(buf);
textFieldIP.setText(getValue(s, "IP:"));
textFieldPort.setText(getValue(s, "PORT:"));
} catch(Exception e){
}
}
public void run(){
while( thread != null ){
try {
Thread.sleep(1000);
labelMsg.setText("Waiting for connection");
getImage();
canvas.repaint();
labelMsg.setText("OK("+ width + "," + height +")");
} catch(Exception err){
String msg = err.getMessage();
System.out.println(msg);
labelMsg.setText(msg);
thread = null;
btnCtrl.setLabel("START");
break;
}
}
}
public void actionPerformed(ActionEvent e){
if(e.getSource() == btnCtrl){
if( thread != null){
thread = null;
btnCtrl.setLabel("START");
} else {
labelMsg.setText("started !");
thread = new Thread(this);
thread.start();// runの実行
btnCtrl.setLabel("STOP");
}
}
}
public void getImage() throws Exception {
String ip= textFieldIP.getText();
int port = Integer.parseInt(textFieldPort.getText());
System.out.println(ip + ":" + port);
Socket socket = new Socket(ip,port);
ImageInputStream inputStream = ImageIO.createImageInputStream(socket.getInputStream());
bufferedImage = ImageIO.read(inputStream);
width = bufferedImage.getWidth(this);
height = bufferedImage.getHeight(this);
canvas.setSize(width,height);
System.out.println("bufferedImage" + bufferedImage.toString());
}
public void getImage_ok(){
try{
Socket socket = new Socket("127.0.0.1",3000);
InputStream inputStream = socket.getInputStream();
bufferedImage = ImageIO.read(inputStream);
System.out.println("bufferedImage" + bufferedImage.toString());
}
catch(Exception e){
}
}
public void getImage_2(){
try{
byte []buf = new byte[1000000];
int count = 0;
Socket socket = new Socket("127.0.0.1",3000);
InputStream inputStream = socket.getInputStream();
for(;;){
int c = inputStream.read();
if( c == -1 ) break;
buf[count++] = (byte) c;
}
System.out.println("受信サイズ:" + count);
System.out.println("bufferedImage" + bufferedImage.toString());
}
catch(Exception e){
}
}
public void getImage_1(){
try{
InputStream inputStream = new FileInputStream(new File("cat.jpg"));
bufferedImage = ImageIO.read(inputStream);
System.out.println("bufferedImage" + bufferedImage.toString());
}
catch(Exception e){
}
}
}
Main-Class: getp.PaintImage Class-Path: getpaint.jar .上記を 「PaintImage.java」 と、「getpaint.MF.txt」を 「getp」の名前のフォルダに入れて、次のように実行すれば、「getpaint.jar」の作品ができます。
javac -source 1.6 -target 1.6 getp\PaintImage.java jar cmvf .\getp\getpaint.MF.txt .\getpaint.jar .\getp\*.classgetpaint_work.zipからソースなどがダウンロードできます。