質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.35%

Unityで、クリックしたピクセルの色を取得したい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,991

hokusou7500

score 18

前提・実現したいこと

Unityで、ウェブカメラで読み込んだ画像をクリックしてそのクリックしたピクセルの色を取得するというものを作っています。

発生している問題・エラーメッセージ

ウェブカメラで映像を映し出し、クリックしたピクセルのカラーコードを表示するというところまでいったのですが表示しているカラーコードが明らかにクリックしたピクセルの色ではないカラーコードになってしまっています。
実行画面
この画像は実行してみたところになります。ポインタが指すところをクリックしたところで、右のパネルに取得した色を表示しています。このように、白っぽい部分をクリックしているにも関わらず実際に表示された色はグレーに近い色になってしまっています。

該当のソースコード

以下がこのプロジェクトで使用しているスクリプトのソースコードになります。

using UnityEngine;
using UnityEngine.UI;

public class WebCameraTest : MonoBehaviour
{
    public RawImage rawImage;

    WebCamTexture webCamTexture;


    void Start()
    {
      webCamTexture = new WebCamTexture();
      rawImage.texture = webCamTexture;
      webCamTexture.Play();
    }

    // Update is called once per frame
    void update ()
    {      

    }
}
using UnityEngine;


public class GetColor : MonoBehaviour
{
    public Color color;
    private Texture2D tex = null;

    void Start()
    {
        tex = new Texture2D(1,1, TextureFormat.RGB24, false);
    }

    public void Onclick()
    {
        Vector2 pos = Input.mousePosition ;
        tex.ReadPixels(new Rect(pos.x, pos.y, 1, 1), 0, 0);
        color = tex.GetPixel(0,0);
                Debug.Log(color);
    }
}
using UnityEngine;

public class UpdateColor : MonoBehaviour
{
    private GetColor getColor;

    void Start()
    {
        getColor = GameObject.FindObjectOfType<GetColor>();
    }

    // Update is called once per frame
    void Update()
    {
        GetComponent<Renderer>().material.color = getColor.color;
                Debug.Log(getColor.color);
                Debug.Log(GetComponent<Renderer>().material.color);
        string save_1_color = ColorUtility.ToHtmlStringRGB(getColor.color);
        Debug.Log(save_1_color);
    }
}


WebCameraTestおよびGetColorはRawImageに、UpdateColorはPlaneにアタッチしてあります。
構成

補足情報(FW/ツールのバージョンなど)

Unity 2019.2.9f1、VisualStudio2015での開発です。

何卒ご教授のほどよろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

Input.mousePositionの位置からtex.ReadPixelsで色を取っていることから察しますに、もしかしてWebCamTexture上からだけでなく画面全体から色を取る必要があるのでしょうか?
もしそうでしたら、色取りのタイミングを変えてやるといいかもしれません。

using System.Collections;
using UnityEngine;

public class GetColor : MonoBehaviour
{
    public Color color;
    private Texture2D tex = null;

    void Start()
    {
        tex = new Texture2D(1, 1, TextureFormat.RGB24, false);
    }

    public void OnClick()
    {
        StartCoroutine(GetColorCoroutine());
    }

    private IEnumerator GetColorCoroutine()
    {
        // 色取得メソッドをコルーチン化し、実際の色取得をフレーム末尾まで遅延させて
        // 画面のレンダリングが完了してから色を取得するようにする
        yield return new WaitForEndOfFrame();
        Vector2 pos = Input.mousePosition;
        tex.ReadPixels(new Rect(pos.x, pos.y, 1, 1), 0, 0);
        color = tex.GetPixel(0, 0);
        Debug.Log(color);
    }
}

それともWebCamTexture上だけに絞った方が望ましいでしょうか?
その場合は、下記のように色取り方法を変更してみてはいかがでしょう。

using UnityEngine;
using UnityEngine.UI;

public class GetColor : MonoBehaviour
{
    public Color color;

    // texは使用しない
    // private Texture2D tex = null;

    void Start()
    {
        // texは使用しない
        // tex = new Texture2D(1, 1, TextureFormat.RGB24, false);
    }

    public void OnClick()
    {
        // Input.mousePositionはゲーム画面全体の中でのマウスポインタの位置を示しているので
        // RawImageに映されているWebCamTextureから正しく色を取るにはそのままでは使えず、座標変換が必要なはず
        Vector2 pos = Input.mousePosition;

        // まず自分自身のRectTransform...つまりRawImageのRectTransformを取得し...
        RectTransform rectTransform = transform as RectTransform;

        // 自分自身が所属しているCanvasも取得し...
        Canvas rootCanvas = rectTransform.GetComponentInParent<Canvas>().rootCanvas;

        // posを自分自身のローカル座標に直して...
        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            rectTransform,
            pos,
            rootCanvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : rootCanvas.worldCamera,
            out Vector2 localPos);

        // さらにUV座標に換算し...
        Rect rect = rectTransform.rect;
        Vector2 uv = (localPos - rect.position) / rect.size;

        // RawImage経由でWebCamTextureのサイズを調べ...
        WebCamTexture webCamTexture = this.GetComponent<RawImage>().texture as WebCamTexture;
        Vector2Int webCamTexSize = new Vector2Int(webCamTexture.width, webCamTexture.height);

        // UV座標をピクセル単位の位置に換算し...
        Vector2 texPos = uv * webCamTexSize;
        Vector2Int texPosInt = new Vector2Int(
            Mathf.Clamp((int)texPos.x, 0, webCamTexSize.x - 1),
            Mathf.Clamp((int)texPos.y, 0, webCamTexSize.y - 1));

        // WebCamTextureから色を取得する
        color = webCamTexture.GetPixel(texPosInt.x, texPosInt.y);
        Debug.Log(color);
    }
}

とはいえ、OnClickRawImage上のクリックイベントを引き金に実行しているのでしたらどちらの方式でも大差ないかもしれませんね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/11/06 14:59

    詳しい回答をいただきありがとうございます。教えていただいたコードを用いてやってみたところうまくいきました!!フォローさせていただきましたので、今後またお世話になることがあるかもしれませんがよろしくお願い致します。

    キャンセル

+1

間違っていたらすみません。
Input.mousePositionとReadPixelsの座標系が違うせいで狙ったのと違うピクセルを拾っているのではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る