Qt OpenCV画像処理 測長 -画像特定箇所判定

◆プログラムの目的:画像から一部のみを取得し、測長する。

◆処理手順概要:

画像取得→2値化→輪郭抽出→ある一定の太さのものだけ測長(太いもの、細いもの)

※作成中のため, imshowにて表示 今後修整予定

◆環境

windows10

visualStudio community 2015

Qt5.7

C++

openCV3.4.6 (openCV4は対応していない)

◆ソースコード

※main.cpp はデフォルトのまま


※MainWindow.cpp はデフォルトのまま(まだ作成していないので imshowと空白のGUI表示になる)

◆test_openCV_measure.pro

#-------------------------------------------------

#
# Project created by QtCreator 2019-05-25T16:17:48
#
#-------------------------------------------------

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = test_openCV_measure
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += main.cpp\
mainwindow.cpp

HEADERS += mainwindow.h

FORMS += mainwindow.ui

win32:DEPENDPATH += "C:\opencv\build\include"
win32:INCLUDEPATH += "C:\opencv\build\include"
//win32:LIBS += -L"C:\opencv\build\x64\vc14\lib"
win32:LIBS += -L"C:\opencv\build\x64\vc15\lib"
//win32:LIBS += -lopencv_core245 -lopencv_highgui245 -lopencv_imgproc245
win32:LIBS += -lopencv_world346


◆mainwindow.h

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H


◆mainwindow.cpp

//流用元:https://cvtech.cc/measure

//openCV 3.4.6 使用 //openCV4はNG:関数返り値など違うため
//
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "opencv2/world.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <QDebug>

using namespace cv;
using namespace std; //追加 https://cvtech.cc/measure/3/

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

//画像の表示と2値化(白黒) https://cvtech.cc/measure/2
//Mat img = imread("root.jpg", IMREAD_UNCHANGED);
Mat img = imread("C:/work/qt/test_openCV_measure/root.jpg", IMREAD_UNCHANGED);
Mat gray_img;
//cvtColor(img, gray_img, CV_BGR2GRAY);
cv::cvtColor(img, gray_img, COLOR_BGR2GRAY); //画像の2値化(白黒)
Mat bin_img;
threshold(gray_img, bin_img, 0, 255, THRESH_BINARY|THRESH_OTSU);
bin_img = ~bin_img;
Mat bin_img_copy=bin_img.clone(); //追加 https://cvtech.cc/measure/4
Mat element = Mat::ones(9,9,CV_8UC1); //追加 //追加 https://cvtech.cc/measure/4
//imshow("IMAGE",bin_img); //2値化(白黒)された画像の表示
//waitKey(10000);
//画像の表示 https://cvtech.cc/measure/2

//findContours関数で輪郭を検出する 追加ここから https://cvtech.cc/measure/3/
vector<vector<Point> > contours;
//findContours(bin_img, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
//findContours 必ずopenCV3 を使うことopenCV4 では 関数返り値が違うために、正常に動作しないなどがある
//参考:http://opencv.jp/opencv-2svn/cpp/structural_analysis_and_shape_descriptors.html
//CV_RETR_LIST すべての輪郭を抽出しますが,一切の階層構造を保持しません
//CV_CHAIN_APPROX_NONE すべての輪郭点を完全に格納します.つまり,この手法により格納された任意の隣り合う2点は,互いに8近傍に存在します.
cv::findContours(bin_img, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
double contour_len=0;
for(int i = 0; i < contours.size(); ++i) {
contour_len += arcLength(contours.at(i),1);
}
//cout<<"estimated root length = "<<contour_len/2<<endl;
qDebug() <<"estimated root length = "<< QString::number((contour_len)/2)<<endl; //測長結果表示
//imshow("IMAGE",bin_img); //画像全体の輪郭イメージ表示
//waitKey(10000); //入力を待つ
//追加ここまで https://cvtech.cc/measure/3/

//追加ここから https://cvtech.cc/measure/4/
//erode(bin_img_copy, bin_img_copy, element, Point(-1,-1), 1);
cv::erode(bin_img_copy, bin_img_copy, element, Point(-1,-1), 1);
imshow("IMAGE_main_root",bin_img_copy);
vector<vector<Point> > contours_main;
//findContours(bin_img_copy, contours_main, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
cv::findContours(bin_img_copy, contours_main, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
double contour_len_main=0;
for(int i = 0; i < contours_main.size(); ++i) {
contour_len_main += arcLength(contours_main.at(i),0);
}
//cout<<"estimated root length (main) = "<<contour_len_main/2<<endl;
//cout<<"estimated root length (lateral) = "<<(contour_len-contour_len_main)/2<<endl;
//画像一部を取り出して、測長結果を表示する
qDebug() <<"estimated root length (main) = "<< QString::number(contour_len_main/2)<<endl;
//画像一部を取り出して、測長結果を表示する
qDebug() <<"estimated root length (lateral) = "<<QString::number((contour_len-contour_len_main)/2 )<<endl;
//追加ここまで https://cvtech.cc/measure/4/

return;

}

MainWindow::~MainWindow()
{
delete ui;
}


◆mainwindow.cpp