Open14

Memo

ukaiukai
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <vector>

static const int NUM_BUFFERS = 2;  // 同時に処理するバッファの数を定義
std::mutex mtx[NUM_BUFFERS];        // 各バッファに対応するミューテックス
std::condition_variable cv[NUM_BUFFERS];  // 各バッファの条件変数
bool buffer_ready[NUM_BUFFERS] = { false, false };  // 各バッファの準備状態を保持
std::atomic<bool> keep_running{ true };  // スレッドの継続実行を制御する原子変数
std::vector<std::thread> threads;  // スレッドを管理するベクター

// データ処理を行う関数
void processData(int index)
{
    while (keep_running) {  // 実行中フラグがtrueの間、ループ
        std::unique_lock<std::mutex> lk(mtx[index]);  // 対応するミューテックスをロック
        cv[index].wait(lk, [index] { return buffer_ready[index]; });  // バッファの準備が整うまで待機

        std::cout << "Data processed: " << index << std::endl;  // データ処理完了を出力
        buffer_ready[index] = false;  // バッファの準備状態をリセット
    }
}

// バッファ準備イベントをシミュレートする関数
void onNewBufferEvent(int index)
{
    while (keep_running) {  // 実行中フラグがtrueの間、ループ
        {
            std::lock_guard<std::mutex> lk(mtx[index]);  // 対応するミューテックスをロック
            std::cout << "Buffer prepared: " << index << std::endl;  // バッファ準備完了を出力
            buffer_ready[index] = true;  // バッファの準備状態をtrueに設定
        }
        cv[index].notify_one();  // 条件変数を通じて、バッファ準備完了を通知

        std::this_thread::sleep_for(std::chrono::seconds(1));  // 1秒間スリープ
    }
}

// メイン関数
int main()
{
    for (int i = 0; i < NUM_BUFFERS; ++i) {
        threads.emplace_back(processData, i);  // データ処理スレッドを起動
        threads.emplace_back(onNewBufferEvent, i);  // バッファ準備スレッドを起動
    }

    std::this_thread::sleep_for(std::chrono::seconds(10));  // 10秒間プログラムを実行

    keep_running = false;  // 実行中フラグをfalseにしてスレッドの終了を指示
    for (auto& th : threads) th.join();  // すべてのスレッドが終了するまで待機

    return 0;
}

ukaiukai
    HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);

    // 現在のモードを取得
    DWORD prev_mode;
    GetConsoleMode(hInput, &prev_mode);

    // QUICK_EDIT_MODEを無効にする
    SetConsoleMode(hInput, prev_mode & ~ENABLE_QUICK_EDIT_MODE);
ukaiukai
  • ScottPlot 4.x
    formsPlot.Configuration.Pan = false;
    formsPlot.Configuration.Zoom = false;
    formsPlot.Configuration.ScrollWheelZoom = false;
    formsPlot.Configuration.MiddleClickDragZoom = false;
  • ScottPlot 5.x
    formsPlot1.Interaction =
        new ScottPlot.Control.Interaction(formsPlot1) { Inputs = new() };
ukaiukai
    double[] data = { 1.0, 2.0, 3.0, 4.0 };

    // 配列をMatに変換
    Mat matData = Mat.FromArray(data);

    // 配列をInputArrayに変換
    InputArray inputArray = InputArray.Create(data);
ukaiukai
   // 99.0% CI の範囲外のピクセル数のパーセンテージ

   Cv2.MeanStdDev(image, out var mean, out var stdDev);

   // 2.576σ interval (approximately 99.0% confidence interval)
   double lowerBound = mean[0] - 2.576 * stdDev[0];
   double upperBound = mean[0] + 2.576 * stdDev[0];

   // ヒストグラムを計算
   Mat hist = new Mat();
   int histSize = 256;
   Rangef range = new Rangef(0, 256);
   Cv2.CalcHist(new Mat[] { image }, new int[] { 0 }, null, hist, 1, new int[] { histSize }, new Rangef[] { range });

   // 外れ値のカウント
   int totalPixels = image.Rows * image.Cols;
   int outlierCount = 0;

   for (int i = 0; i < histSize; i++)
   {
      double pixelValue = i;
      double count_ = hist.Get<float>(i);

      if (pixelValue < lowerBound || pixelValue > upperBound)
      {
         outlierCount += (int)count_;
      }
   }

   double outlierPercentage = (double)outlierCount / totalPixels * 100;

   Trace.WriteLine($"Percentage of outliers: {outlierPercentage}%");
ukaiukai
   // 全ピクセルの内の上限側0.5%と下限側の0.5%のピクセルの境の輝度値

   // ヒストグラムを計算
   Mat hist = new Mat();
   int histSize = 256;
   Rangef range = new Rangef(0, 256);
   Cv2.CalcHist(new Mat[] { image }, new int[] { 0 }, null, hist, 1, new int[] { histSize }, new Rangef[] { range });

   // 累積ヒストグラムを計算
   Mat cumHist = hist.Clone();
   for (int i = 1; i < histSize; i++)
   {
      cumHist.Set<float>(i, cumHist.Get<float>(i) + cumHist.Get<float>(i - 1));
   }

   // 累積ヒストグラムを正規化してパーセンテージに変換
   Cv2.Normalize(cumHist, cumHist, 0, 1, NormTypes.MinMax);

   // 境界値を見つける
   double lowerPercentileValue = 0.005;
   double upperPercentileValue = 0.995;

   int lowerBoundaryValue = 0;
   int upperBoundaryValue = 0;

   // 下限側0.5%の境界値
   for (int i = 0; i < histSize; i++)
   {
      if (cumHist.Get<float>(i) >= lowerPercentileValue)
      {
         lowerBoundaryValue = i;
         break;
      }
   }

   // 上限側0.5%の境界値
   for (int i = 0; i < histSize; i++)
   {
      if (cumHist.Get<float>(i) >= upperPercentileValue)
      {
         upperBoundaryValue = i;
         break;
      }
   }

   Trace.WriteLine($"Lower 0.5% boundary value: {lowerBoundaryValue}");
   Trace.WriteLine($"Upper 0.5% boundary value: {upperBoundaryValue}");
ukaiukai
#include <opencv2/opencv.hpp>

cv::Mat extractChannel(const cv::Mat& input, int offsetX, int offsetY)
{
    cv::Rect roi(offsetX, offsetY, input.cols - offsetX, input.rows - offsetY);
    cv::Mat output = input(roi);
    cv::copyMakeBorder(output, output, 0, offsetY, 0, offsetX, cv::BORDER_CONSTANT, cv::Scalar(0));
    
    cv::Mat resized;
    cv::resize(output, resized, cv::Size(), 0.5, 0.5, cv::INTER_NEAREST);
    return resized;
}
ukaiukai
  • この関数は、4つのチャネルをそれぞれ拡大し、マスクを使用して1つのマトリックスにマージします。
#include <opencv2/opencv.hpp>

cv::Mat mergeChannel(const cv::Mat& channel00, const cv::Mat& channel10, const cv::Mat& channel01, const cv::Mat& channel11)
{
    cv::Mat resized00, resized10, resized01, resized11;
    cv::resize(channel00, resized00, cv::Size(), 2, 2, cv::INTER_NEAREST);
    cv::resize(channel10, resized10, cv::Size(), 2, 2, cv::INTER_NEAREST);
    cv::resize(channel01, resized01, cv::Size(), 2, 2, cv::INTER_NEAREST);
    cv::resize(channel11, resized11, cv::Size(), 2, 2, cv::INTER_NEAREST);

    cv::Mat temp = (cv::Mat_<uchar>(2, 2) << 1, 0, 0, 0);
    cv::Mat mask;
    cv::repeat(temp, resized00.rows / 2 + 1, resized00.cols / 2 + 1, mask);

    cv::Mat merged = cv::Mat::zeros(resized00.size(), CV_8UC1);
    cv::bitwise_or(merged, resized00, merged, mask(cv::Rect(0, 0, resized00.cols, resized00.rows)));
    cv::bitwise_or(merged, resized10, merged, mask(cv::Rect(1, 0, resized10.cols, resized10.rows)));
    cv::bitwise_or(merged, resized01, merged, mask(cv::Rect(0, 1, resized01.cols, resized01.rows)));
    cv::bitwise_or(merged, resized11, merged, mask(cv::Rect(1, 1, resized11.cols, resized11.rows)));

    return merged;
}
ukaiukai
bool compare(const cv::Mat& a, const cv::Mat& b)
{
    cv::Mat result;
    cv::compare(a, b, result, cv::CMP_NE);
    return cv::countNonZero(result) == 0;
}
ukaiukai
    cv::Mat bayer = cv::imread("bayerRG8.png", cv::IMREAD_GRAYSCALE);

    cv::Mat output00 = extractChannel(bayer, 0, 0);
    cv::Mat output10 = extractChannel(bayer, 1, 0);
    cv::Mat output01 = extractChannel(bayer, 0, 1);
    cv::Mat output11 = extractChannel(bayer, 1, 1);

    cv::Mat merged = mergeChannel(output00, output10, output01, output11);

    bool flag = compare(bayer, merged);
ukaiukai
    cv::Mat bilinearInterpolation(const cv::Mat& input64F, int destWidth, int destHeight)
    {
        cv::Mat output64F(destHeight, destWidth, CV_64F);

        int sourceWidth = input64F.cols;
        int sourceHeight = input64F.rows;

        double scaleX = static_cast<double>(sourceWidth - 1 - 1e-3) / (destWidth - 1);
        double scaleY = static_cast<double>(sourceHeight - 1 - 1e-3) / (destHeight - 1);

        for (int y = 0; y < destHeight; y++)
        {
            for (int x = 0; x < destWidth; x++)
            {
                // ターゲット座標を元のスケールに変換
                double gx = x * scaleX;
                double gy = y * scaleY;

                // 4つの隣接点を取得
                int blockX = static_cast<int>(floor(gx));
                int blockY = static_cast<int>(floor(gy));

                double p1 = input64F.at<double>(blockY, blockX);
                double p2 = input64F.at<double>(blockY, blockX + 1);
                double p3 = input64F.at<double>(blockY + 1, blockX + 1);
                double p4 = input64F.at<double>(blockY + 1, blockX);

                // 隣接点からの距離を計算
                double alphaX = gx - blockX;
                double alphaY = gy - blockY;

                // バイリニア補間
                double r1 = p1 * (1 - alphaX) + p2 * alphaX;
                double r2 = p4 * (1 - alphaX) + p3 * alphaX;
                double p = r1 * (1 - alphaY) + r2 * alphaY;

                output64F.at<double>(y, x) = p;
            }
        }

        return output64F;
    }