LoginSignup
1
2

More than 3 years have passed since last update.

ラズパイとカメラを使用してカラーセンサー作成

Last updated at Posted at 2020-08-20

要望 加工品のつまり、終了を見抜きたい

機械工作工場にて自動レーンでの製品のつまり、最終加工品の完了した時を知りたい。
製品のつまり.jpg
バルブの赤いハンドルの位置(開閉表示)を知りたい。
バルブの状態.png

製品は黄色、背景(レーン)は白、青、又は黒の原色。
既製品のセンサーが高すぎるので安く作って欲しいとの要望。

完成品

ラズパイをローカルWIFIにつなげて。
http://"ラズパイのIPアドレス"/home.php

加工品.jpg

抜き出し場所.JPG

カメラ画像から当該箇所を指定して抜き出す。
色範囲を指定して、色範囲に入った場合GPIOを出力する。
GPIOの出力にて警報ランプを起動させる。
警報解除は警報リセットにて行う。

ラズパイ環境設定

python OpenCV ダウンロード
参考サイト 計算機科学を学んだソフトウェア技術者の経験やメモなどの記録様

sudo apt-get install libopencv-dev
sudo apt-get install python-opencv

アパッチダウンロード
参考サイト @mono_taro様
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install apache2
apachectl -v

phpダウンロード
参考サイト The modern stone age.様
sudo apt install php7.2 libapache2-mod-php7.2

php及びhtml作成

/var/www/html/home.php
<html>
<head>
<meta http-equiv="content-type" charset="utf-8">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="refresh" content="5" >
</head>
</html>
<form action="set.php" method="get">
<body>
    <h1>カメラ画像</h1>
    <?php
        $lines_reset = file('/home/pi/Documents/reset.csv');
        foreach($lines_reset as $line_reset){
            $data_reset = explode(',',$line_reset);
        if ($data_reset[0] == 1){
        echo "<FONT COLOR=\"RED\"> 現在警報動作中 解除する場合は下ボタンにて </FONT>";}
        }
    ?>
        <img src="1.jpg?1">
        <h2>抜出画像</h2>
        <img src="2.jpg?1">
</body>
<?php
$lines = file('/home/pi/Documents/color.csv');
foreach($lines as $line){
    $data = explode(',',$line); 
    echo '<p>';
    echo ' 赤色R',$data[0];
    echo ' 緑色G',$data[1];
    echo ' 青色B',$data[2];    
    echo '</p>';
}
?>
<a href="./set.html">設定画面</a>
<a href="./reset.html">警報リセット</a>
</form>
/var/www/html/set.html
<form action="set.php" method="get">
<p>
<a href="./home.php">戻る</a>
</p>
<img src="1.jpg">
<p>色の範囲指定</p>
<p>赤下限: <input type="number" name="r_2_1" value="1" min="0" max="255"></p>
<p>赤上限: <input type="number" name="r_2_2" value="1" min="0" max="255"></p>
<p>緑下限: <input type="number" name="g_2_1" value="1" min="0" max="255"></p>
<p>緑上限: <input type="number" name="g_2_2" value="1" min="0" max="255"></p>
<p>青下限: <input type="number" name="b_2_1" value="1" min="0" max="255"></p>
<p>青上限: <input type="number" name="b_2_2" value="1" min="0" max="255"></p>
<p>画像抜出ファイル 上下は上からの距離、左右は左からの距離</p>
<p>top: <input type="number" name="top" value="1" min="0" max="2000"></p>
<p>下bot: <input type="number" name="bot" value="100" min="0" max="2000"></p>
<p>left: <input type="number" name="left" value="1" min="0" max="2000"></p>
<p>右right: <input type="number" name="right" value="100" min="0" max="2000"></p>
<p>シャッター間隔、規定回数</p>
<p>シャッター間隔 秒(s): <input type="number" name="interval" value="60" min="10" max="6000"></p>
<p>回数: <input type="number" name="nutime" value="1" min="1" max="100"></p>
<input type="submit" />
<p> </p>
<p>補足色説明</p>
<p>赤色 R255 G0 B0</p>
<p>黒 R0 G0 B0</p>
<p>白 R255 G255 B255</p>
<p>黄色 R255 G255 B0</p>
<p>灰色 R128 G128 B128</p>
<p>その他の色はRGB色で検索願います。</p>
<p>規定回数とは連続で指定範囲内に入った回数の時、リレーが作動する回数</p>
</form>
/var/www/html/set.php
<meta http-equiv="content-type" charset="utf-8">
<?php 
     $r_2_1=htmlspecialchars($_GET["r_2_1"],ENT_QUOTES);
     $r_2_2=htmlspecialchars($_GET["r_2_2"],ENT_QUOTES);
     $g_2_1=htmlspecialchars($_GET["g_2_1"],ENT_QUOTES);
     $g_2_2=htmlspecialchars($_GET["g_2_2"],ENT_QUOTES);
     $b_2_1=htmlspecialchars($_GET["b_2_1"],ENT_QUOTES);
     $b_2_2=htmlspecialchars($_GET["b_2_2"],ENT_QUOTES);
     $top=htmlspecialchars($_GET["top"],ENT_QUOTES);
     $bot=htmlspecialchars($_GET["bot"],ENT_QUOTES);
     $left=htmlspecialchars($_GET["left"],ENT_QUOTES);
     $right=htmlspecialchars($_GET["right"],ENT_QUOTES);
     $interval=htmlspecialchars($_GET["interval"],ENT_QUOTES);
     $nutime=htmlspecialchars($_GET["nutime"],ENT_QUOTES);
?>
<body>
<?php echo $_GET["r_2_1"]; ?>
<?php 
$data = [
    [$_GET["r_2_1"], $_GET["r_2_2"], $_GET["g_2_1"], $_GET["g_2_2"], $_GET["b_2_1"], $_GET["b_2_2"],
    $_GET["top"], $_GET["bot"], $_GET["left"], $_GET["right"],
    $_GET["interval"], $_GET["nutime"]],
];
$fp = fopen('/home/pi/Documents/position.csv', 'w');
foreach ($data as $line) {
    fputcsv($fp, $line);
}
fclose($fp);
?>
<p>
<a href="./home.php">戻る</a>
</p>
/var/www/html/reset.html
<meta http-equiv="content-type" charset="utf-8">
<meta http-equiv="Cache-Control" content="no-cache">
<form action="reset.php" method="get">
<input type="submit" />
</form>
/var/www/html/reset.php
<meta http-equiv="content-type" charset="utf-8">
<?php 
$data = [["0"]];
$fp = fopen('/home/pi/Documents/reset.csv', 'w');
foreach ($data as $line) {
    fputcsv($fp, $line);}
fclose($fp);
?>
<p>
<a href="./home.php">戻る</a>
</p>

python 及びCSV作成

/home/pi/Documents/gazou.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import cv2, os
import numpy as np
import csv
import time
import RPi.GPIO as GPIO
time.sleep(60)#ラズパイ起動時の待機時間
#GPIO設定
PIN = 14
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN, GPIO.OUT)
#イメージファイルの保存場所
image_file = '/var/www/html/1.jpg' #写真撮影
image_file_2 = '/var/www/html/2.jpg' #検証1
#読み込み用CSVの場所
poss = '/home/pi/Documents/position.csv'
colo_0 = '/home/pi/Documents/color0.csv'
colo_1 = '/home/pi/Documents/color.csv'
poss_reset = '/home/pi/Documents/reset.csv'
while True:
    try :
        with open(poss) as data0:#切り出し場所を読み取る
            reader = csv.reader(data0)
            data1 = [row for row in reader]
        #範囲読み取り
        r_2_1 = int(data1[0][0]) #赤下限 img2
        r_2_2 = int(data1[0][1]) #赤上限 img2
        g_2_1 = int(data1[0][2]) #緑下限 img2
        g_2_2 = int(data1[0][3]) #緑上限 img2
        b_2_1 = int(data1[0][4]) #青下限 img2
        b_2_2 = int(data1[0][5]) #青上限 img2
        #img2.jpgの切り出し部分
        top_2   = int(data1[0][6])
        bot_2   = int(data1[0][7])
        left_2  = int(data1[0][8])
        right_2 = int(data1[0][9])
        #繰り返し秒数及び動作確認数
        jobs_s = int(data1[0][10])
        time.sleep(jobs_s)
        with open(poss_reset) as data_reset:#リセットCSV読み取り
            reader_reset = csv.reader(data_reset)
            data_reset1 = [row for row in reader_reset]
        data_resset2 = int(data_reset1[0][0])
        with open(colo_0) as data2:#書き込み用のデフォルトデータを読み込む
            reader = csv.reader(data2)
            data3 = [row for row in reader]
        cam = cv2.VideoCapture(0)
        # カメラから映像を読み込む
        _, img = cam.read()
        # 画像ファイルとして書き出す
        img2 = img[top_2 : bot_2, left_2: right_2]
        #イメージ保存
        cv2.imwrite(image_file, img)
        cv2.imwrite(image_file_2, img2)
        # RGB平均値を出力
        # flattenで一次元化しmeanで平均を取得 
        r2 = img2.T[2].flatten().mean()
        g2 = img2.T[1].flatten().mean()
        b2 = img2.T[0].flatten().mean()     
        if data_resset2 == 0:
            GPIO.output(PIN, GPIO.LOW) #とりあえず切る
            if r_2_1 < r2 < r_2_2 and g_2_1 < g2 < g_2_2 and b_2_1 < b2 < b_2_2:
                GPIO.output(PIN, GPIO.HIGH)
                data_resset2 = 1
        # RGB平均値を取得
        data3[0][0] = '%.0f' % r2
        data3[0][1] = '%.0f' % g2
        data3[0][2] = '%.0f' % b2
        #CSVを保存
        with open(colo_1, 'w') as f:
            writer = csv.writer(f)
            for data4 in data3:
                writer.writerow(data4)
        data_reset1[0][0] = data_resset2
        with open(poss_reset, 'w') as f:
            writer = csv.writer(f)
            for data_reset2 in data_reset1:
                writer.writerow(data_reset2)
        # 事後処理
        cam.release()
        cv2.destroyAllWindows()
    except:
        time.sleep(30)
        pass
/home/pi/Documents/position.csv
1,1,1,1,1,1,1,100,1,100,60,1
/home/pi/Documents/color0.csv
100,100,100,100,100,100
/home/pi/Documents/color.csv
100,100,100,100,100,100
/home/pi/Documents/reset.csv
0

起動時にpythonを起動する設定をする。

sudo にて gazou.pyを自動起動する。
sudo でないと/var/www/html/にjpgの画像を書き込まない
参考サイト@yuru-camper様

使用したカメラ

C270N HD WEBCAM
logicool様サイト

将来やりたい事

設定画面が下記のように設定しにくいので抜き出し箇所はマウスで選択できるようにしたい。
色設定もマウスで決定できるようにしたい。
現在の状態だと設定がトライアンドエラーをたくさん繰り返さなくてはいけない。
設定画面.JPG

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2