【QTコースデザイン】 3つ:グレースケール、画像の2値化(閾値調整可能)、3×3平均値フィルタリング

フロントエンド記事とナビゲーションインデックス

ナビゲーションインデックスポスト
前記事、コースデザインの第2記事

序文

前章で画像を開く機能が一旦完成しましたので、本章では画像処理リンクの作成に入ります。

グレースケール

画像のグレースケールの原理

カラー画像では、各ピクセルの色は R、G、B の 3 つの値によって決まります。各値は 0 ~ 255 に分布しており、255、255、255を組み合わせることができます。
グレースケール画像の RGB 値は 3 つの同一の値であり、1 ピクセルの変動範囲は 255 です。そのため、デジタル画像処理では、一般に、後続の画像をより正確にするために、さまざまな形式の画像をグレースケール画像に変換します。計算が少なくなります。グレースケール イメージの記述は、カラー イメージと同様に、イメージ全体の全体的および局所的な色度および輝度レベルの分布と特性を反映します。画像のグレースケール処理は 2 つの方法で実現できます。

方法 1

各ピクセルの R、G、B の 3 つの成分の平均を求め、この平均をこのピクセルの 3 つの成分に割り当てます。

方法 2

YUV 色空間によると、Y 成分の物理的意味は点の明るさです。この値は明るさのレベルを反映します。RGB 色空間と YUV 色空間の間の変化する関係に従って、明るさ Y と 3 つの色空間の対応関係は変わります。 R、G、B の色成分を確立できます: Y=0.3R+0.59G+0.11B、この輝度値を使用して画像の階調値を表現します。

便宜上、ここでは方法 1、つまり Gray=(R+G+B)/3 を直接採用できます。

コード

//灰度化
QImage MainWindow::gray(QImage image){
    
    
    QImage newImage =image.convertToFormat(QImage::Format_ARGB32);
    QColor oldColor;

        for(int y = 0; y < newImage.height(); y++)
        {
    
    
            for(int x = 0; x < newImage.width(); x++)
            {
    
    
                oldColor = QColor(image.pixel(x,y));
                int average = (oldColor.red() + oldColor.green() + oldColor.blue()) / 3;
                newImage.setPixel(x, y, qRgb(average, average, average));
            }
        }
        return newImage;
}

グレースケール法の目的は、ターゲット画像の各ピクセルをグレースケール化することであり、最終的な画像はグレースケール画像になります。

//灰度化按钮
void MainWindow::on_GreyBtn_clicked()
{
    
    
    if(srcDirPathList.isEmpty())
    {
    
    
        QMessageBox::information(this,tr("请先选择图片"),
                                 tr("请先选择图片!"));
        return;
    }
    else{
    
    
        QImage image=QImage(srcDirPathList.at(imagenum));
        QImage grayimage=gray(image);
        ui->piclabel->setPixmap(QPixmap::fromImage(ImageSetSize(grayimage,ui->piclabel)));
    }
}

次に、グレースケール ボタン機能を実装するには、グレースケール処理を実行する前に現在の画像が存在するかどうかも確認する必要があります。その効果は次のようになります。
グレースケール
画像を変更したので元の画像を表示する必要があるので、元の画像を表示するボタンの機能も実装します。

//显示原图按钮
void MainWindow::on_YuanTuBtn_clicked()
{
    
    
    if(srcDirPathList.isEmpty())
    {
    
    
        QMessageBox::information(this,tr("请先选择图片"),
                                 tr("请先选择图片!"));
        return;
    }
    else{
    
    
        QImage image=QImage(srcDirPathList.at(imagenum));
        ui->piclabel->setPixmap(QPixmap::fromImage(ImageSetSize(image,ui->piclabel)));
    }
}

ここのコードは何度も登場しているので説明は省略します。

二値化

二値化の原理

二値化とは、画像上のピクセルのグレースケール値を 0 または 255 に設定する処理で、画像全体が白黒はっきり見えるようにする処理です。まず画像をグレースケール化し、次に各グレースケール値を設定したバイナリ調整値と比較する必要があります。調整値より大きいものは直接黒 (255、255、255) に変わり、小さいものは黒になります。調整値は白(0,0,0)となり、2値画像(閾値画像)が得られます。

レイアウト調整

ここで、二値化を調整するための調整バーを追加する必要があります。QT には Qslider クラスが用意されており、水平方向のスライダーを水平スライダー、垂直方向のスライダーを垂直スライダーと呼びます。
レイアウトインターフェース
新構造
期待する効果は、調整バーを任意に変更すると数値が表示され、ラインエディットで数値を任意に変更すると調整バー(0〜255の範囲内)を変更できることです。

バイナリ化されたコードの実装

このコードは上記の原理に基づいて一般に比較的理解しやすく、再帰的にグレースケールを取得し、値を比較し、変更します。

//二值化
QImage MainWindow::TwoSide(QImage grayimage,int value){
    
    
    QImage TwoSideImage =grayimage.convertToFormat(QImage::Format_ARGB32);
    QColor oldColor;
    int ts;
    for(int y = 0; y < grayimage.height(); y++)
    {
    
    
        for(int x = 0; x < grayimage.width(); x++)
        {
    
    
                oldColor = QColor(grayimage.pixel(x,y));
                ts = oldColor.red();
            if(ts<value){
    
    
                ts=0;
            }else{
    
    
                ts=255;
            }
            TwoSideImage.setPixel(x,y, qRgb(ts, ts, ts));

        }
    }
    return TwoSideImage;
}

調整バーの機能設計

まず前者の機能設計を行う。
TwoSidelSlider の属性 maxmum を見つけて 255 に設定します。これは、バイナリの最大値が 255 であることを意味します。最小値は元は 0 であり、調整する必要はありません。
アジャストバーリミット調整
調整バーのジャンプ スロットで valueChanged() を見つけます。つまり、調整バーの値が変更されると、コードが実行されます。

//二值化调节条
void MainWindow::on_TwoSidelSlider_valueChanged(int value)
{
    
    
    if(srcDirPathList.isEmpty()){
    
    
        QMessageBox::information(this,tr("请先选择图片"),
                                 tr("请先选择图片!"));
        return;
    }
    else{
    
    
        QImage image=QImage(srcDirPathList.at(imagenum));//读取当前图片
        QImage grayimage=gray(image);//灰度化
        QImage TwoSideImage=TwoSide(grayimage,value);//二值化
        ui->TwoSideLineEdit->setText(QString::number(value));//改变文本框内值为二值化比对值
        ui->piclabel->setPixmap(QPixmap::fromImage(ImageSetSize(TwoSideImage,ui->piclabel)));//显示二值化图像
    }
}

コードは比較的単純なので、これ以上説明する必要はありません。

2値化テキストボックス機能設計

実際、調整バーを書いた後、テキスト ボックス関数を考えるのは簡単です。コードは次のとおりです。ご質問がある場合は、コメントを読んでください。その他のご質問がある場合は、コメントするか、私にメールを送ってください。プライベートメッセージ。

//二值化文本框
void MainWindow::on_TwoSideLineEdit_textChanged(const QString &arg1)
{
    
    
    if(srcDirPathList.isEmpty()){
    
    
        QMessageBox::information(this,tr("请先选择图片"),
                                 tr("请先选择图片!"));
        return;
    }
    else{
    
    
        int value=arg1.toInt();
        if (value>=0 && value<=255)
        {
    
    
        QImage image=QImage(srcDirPathList.at(imagenum));
        QImage grayimage=gray(image);
        QImage TwoSideImage=TwoSide(grayimage,value);//都是和上面一样的
        ui->TwoSidelSlider->setValue(value);//当文本框内数值改变时,动态变化调节条位置
        ui->piclabel->setPixmap(QPixmap::fromImage(ImageSetSize(TwoSideImage,ui->piclabel)));
        }
        else
        {
    
    
            QMessageBox::information(this,tr("请输入正确数值"),
                                     tr("请输入0-255!"));
            return;
        }
    }
}

機能の二値化部分は完了しましたが、この時点で二値化ボタンが無駄に見えることが判明したので、インターフェイス上に無駄なボタンがないように削除します。
二値化効果図は以下の通りですが、一般的に二値化は難しいものではなく、グレースケールが完成できればスムーズに二値化が進みます。
二値化レンダリング

3x3 平均フィルター

3x3 平均フィルター原理

フィルタリングを定義するには、言語形式を使用します。ピクセルについては、そのドメイン ピクセル (独自の x を含む場合と含まない場合があります) の関連特性を使用して、現在のピクセル値を置き換える値を計算します。
3x3 平均フィルタリングは、各ピクセルに対応する 3x3 フィールド内のすべてのピクセル値の平均を計算し、現在のピクセルを置き換えます。
平均値フィルタリングの原理は比較的単純で、式は次のように表されます
ここに画像の説明を挿入します
: 現在のピクセルを中心として、ウィンドウ内のすべてのグレー値の合計を見つけ、その平均値を中心ピクセルの新しいグレー値として使用します。 。
g(x,y) は近傍の中心ピクセルであり、n は係数テンプレートのサイズに関係します。一般に 3*3 近傍テンプレートの場合、n は 9 に設定されます
ここに画像の説明を挿入します
。の場合、画像の境界を拡張することを考慮する必要があります。操作は、0 または隣接するピクセル値に拡張します。
このコースの時間は比較的限られているため、アルゴリズムの速度の最適化については当面考慮しませんが、後で時間があれば追加します。

平均値フィルターの実装

このコード部分は理解するのが比較的難しいかもしれません。このコード部分については、今後別のブログで説明する予定であり、リンクもここに掲載されます。それについては今は話さないで、このコードを使用して関数を実装しましょう。

//均值滤波
QImage MainWindow::avg(QImage image)
{
    
    
    int kernel [3][3] = {
    
    
        {
    
    1,1,1},
        {
    
    1,1,1},
        {
    
    1,1,1}};
        int sizeKernel = 3;
        int sumKernel = 9;
        QColor color;
         for(int x = sizeKernel/2;x<image.width() - sizeKernel/2;x++)
        {
    
    
           for(int y= sizeKernel/2;y<image.height() - sizeKernel/2;y++)
            {
    
    
                int r = 0;
                int g = 0;
                int b = 0;
                for(int i = -sizeKernel/2;i<=sizeKernel/2;i++)
                {
    
    
                   for(int j = -sizeKernel/2;j<=sizeKernel/2;j++)
                    {
    
    
                     color = QColor(image.pixel(x+i,y+j));
                     r+=color.red()*kernel[sizeKernel/2+i][sizeKernel/2+j];
                     g+=color.green()*kernel[sizeKernel/2+i][sizeKernel/2+j];
                     b+=color.blue()*kernel[sizeKernel/2+i][sizeKernel/2+j];
                    }
                }
                r = qBound(0,r/sumKernel,255);
                g = qBound(0,g/sumKernel,255);
                b = qBound(0,b/sumKernel,255);
                image.setPixel(x,y,qRgb( r,g,b));
            }
        }
         return image;
}

平均値フィルター ボタンの機能は一目瞭然です。

//均值滤波按钮
void MainWindow::on_TXTBtn_clicked()
{
    
     if(srcDirPathList.isEmpty())
    {
    
    
        QMessageBox::information(this,tr("请先选择图片"),
                                 tr("请先选择图片!"));
        return;
    }
    else{
    
    
        QImage image=QImage(srcDirPathList.at(imagenum));
        QImage avgimage=avg(image);
        ui->piclabel->setPixmap(QPixmap::fromImage(ImageSetSize(avgimage,ui->piclabel)));
    }
}

効果比較

この時点で、この章の内容はすべて完了しました。ご質問やバグを見つけた場合は、できるだけ早くご連絡ください。

おすすめ

転載: blog.csdn.net/weixin_43035795/article/details/127975422