Skip to content

剔除背景并找重心

把二值图前景换成任意颜色,背景透明,并提取重心。有很多方法可以实现,需求如果跟我一样可以参考下。

1 剔除背景

QImage图片转换成 Format_Indexed8 类型,可以获取图片的 ColorTable。让后把 ColorTable 的背景色换成自定义的。

static QImage ConvertImageToTransparent(
       QImage image,
       const QRgb &rgb_show = QColor(255, 0, 0).rgb(),
       const QRgb &rgb_bg = QColor(0, 0, 0, 0).rgba());
QImage AspectsLabel::ConvertImageToTransparent(
    QImage image, const QRgb &rgb_show, const QRgb &rgb_bg) {
    QPoint ponit = QPoint(0, 0);
    image = image.convertToFormat(QImage::Format_Indexed8);
    if(image.valid(ponit)) {
        QRgb rgb = image.pixel(ponit);
        QVector<QRgb> rgbVector = image.colorTable();
        for (int i = 0; i < rgbVector.size(); ++i) {
            if(rgbVector.at(i) == rgb ) {
                image.setColor(i, rgb_bg);
            } else {
                image.setColor(i, rgb_show);
            }
        }
    }
    return image ;
}

2 获取图片重心

QImage 没有现成的函数,除非自己遍历像素计算。干脆用opencv吧

static void GravityCenter(QString name, QPointF &center, const qint32 &length);
void AspectsLabel::GravityCenter(QString name, QPointF &center, const qint32 &length) {
    using namespace cv;
    Mat src = imread(name.toLocal8Bit().data(), 0);
    threshold(src, src, 0, 255, THRESH_OTSU);
    vector<vector<Point>>contours;
    vector<Vec4i>hierarchy;
    findContours(src, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
    if (contours.size() == 1) {
        Mat tmp(contours.at(0));
        Moments moment = moments(tmp, false);
        center.setX(cvRound(moment.m10 / moment.m00) - 5);
        center.setY(cvRound(moment.m01 / moment.m00) + length);
    }
}

3 图片叠加

用QPainter一直画就行了

    painter->save();
    qint32 length_blank = abs(width() - height()) / 2;
    qint32 length_pic = this->width() > this->height() ? this->height() : this->width();
    QString pixpath_center = Global::cur_session_.GetFileName(SessionRecord::Asp_Result) +
                             Global::asplist_.at(FileName::Asp_ResultImgs);
    QImage pix =
        QImage(pixpath_center + QString("/%1_src.png").arg(cur_id_));
    QRect pix_rect;
    pix_rect = this->width() > this->height() ?
               QRect(length_blank, 0, length_pic, length_pic) :
               QRect(0, length_blank, length_pic, length_pic);
    painter->drawPixmap(pix_rect, QPixmap::fromImage(pix));
    //
    if(Source == style_) {
        painter->restore();
        return;
    }
    QList<RegionType> region;
    if(this->cur_id_ >= 16 && this->cur_id_ <= 18) {
        region << nuclear_;
    } else if(this->cur_id_ >= 19 && this->cur_id_ <= 21) {
        region << nuclear_up_;
    }
    //
    foreach (auto var, region) {
        QString name = pixpath_center + filelist_region_.at(var).arg(cur_id_);
        QPointF center;
        QRgb rgb_show;
        if(show_tran_) {
            rgb_show = QColor("#" + rgb_list_.at(var)).rgba();
        } else {
            rgb_show = QColor("#80" + rgb_list_.at(var)).rgba();
        }
        pix = ConvertImageToTransparent(QImage(name + "L.png"), rgb_show);
        GravityCenter((name + "L.png"), center, length_blank);
        painter->drawPixmap(pix_rect, QPixmap::fromImage(pix));
        pix = ConvertImageToTransparent(QImage(name + "R.png"), rgb_show);
        GravityCenter((name + "R.png"), center, length_blank);
        painter->drawPixmap(pix_rect, QPixmap::fromImage(pix));
    }
    foreach (auto var, region) {
        QString name = pixpath_center + filelist_region_.at(var).arg(cur_id_);
        QPointF center;
        QString title = "";
        QMap<QString, QVariant> result_map;
        QFont font;
        painter->setPen(Qt::white);
        font.setPointSize(18);
        painter->setFont(font);
        if(show_tag_) {
            title = title_list_.at(var);
        }
        if(show_value_) {
            QString xml_path =
                Global::cur_session_.GetFileName(SessionRecord::Asp_Result) +
                Global::asplist_.at(FileName::Asp_ResultXml);
            XmlUtil::ReadOpencvXml(xml_path, result_map); // 读取文件
        }
        GravityCenter((name + "L.png"), center, length_blank);
        if(show_value_) {
            title = result_map[
                        QString("_%1%2L").arg(cur_id_).arg(title_list_.at(var))].toString();
        }
        painter->drawText(center * length_pic / 512, title);
        GravityCenter((name + "R.png"), center, length_blank);
        if(show_value_) {
            title = result_map[
                        QString("_%1%2R").arg(cur_id_).arg(title_list_.at(var))].toString();
        }
        painter->drawText(center * length_pic / 512, title);
    }
    //
    QFont font;
    painter->setPen(Qt::green);
    font.setPointSize(14);
    painter->setFont(font);
    if(this->cur_id_ >= 16 && this->cur_id_ <= 18) {
        painter->drawText(tagging_weight,
                          this->height() - tagging_height - tagging_interval * 4,
                          QString("核团层面   (%1)").arg(cur_id_));
        painter->drawText(tagging_weight,
                          this->height() - tagging_height - tagging_interval * 3,
                          QString("I:岛叶"));
        painter->drawText(tagging_weight,
                          this->height() - tagging_height - tagging_interval * 2,
                          QString("L:豆状核"));
        painter->drawText(tagging_weight,
                          this->height() - tagging_height - tagging_interval * 1,
                          QString("C:尾状核"));
        painter->drawText(tagging_weight, this->height() - 60 - 25 * 0,
                          QString("IC:内囊后肢"));
    } else if(this->cur_id_ >= 19 && this->cur_id_ <= 21) {
        painter->drawText(tagging_weight,
                          this->height() - tagging_height,
                          QString("核团以上大脑皮层   (%1)").arg(cur_id_));
    }
    painter->restore();