Open14
Memo
#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;
}
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
// 現在のモードを取得
DWORD prev_mode;
GetConsoleMode(hInput, &prev_mode);
// QUICK_EDIT_MODEを無効にする
SetConsoleMode(hInput, prev_mode & ~ENABLE_QUICK_EDIT_MODE);
- 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() };
- ScottPlot 4.x
plt.AxisAuto();
- ScottPlot 5.x
plt.Axes.AutoScale();
double[] data = { 1.0, 2.0, 3.0, 4.0 };
// 配列をMatに変換
Mat matData = Mat.FromArray(data);
// 配列をInputArrayに変換
InputArray inputArray = InputArray.Create(data);
// 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}%");
// 全ピクセルの内の上限側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}");
#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;
}
- この関数は、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;
}
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;
}
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);
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;
}