#include <stdio.h>
#include "opencv2/opencv.hpp"

bool initCamera(cv::String cameraID, cv::VideoCapture &cap)
{
    // create handle and open camera
    cv::VideoCapture camera_cap(cv::CAP_DSHOW);
    cap = camera_cap;
    cap.open(cameraID);
    if (!cap.isOpened())
    {
        std::cerr << "Couldn't open capture." << std::endl;
        return false;
    }

    // set params
    // cap.set(cv::CAP_PROP_CONVERT_RGB,1);
    cap.set(cv::CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G'));
    cap.set(cv::CAP_PROP_FRAME_WIDTH, 1280);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);
    std::cout << "props: \nwidth, height: " << cap.get(cv::CAP_PROP_FRAME_WIDTH) << " " << cap.get(cv::CAP_PROP_FRAME_HEIGHT)
              << "\nfps: " << cap.get(cv::CAP_PROP_FPS) << std::endl;
    return true;
}

void dispVideo(cv::VideoCapture &cap, bool disp_props = false, std::string img_addr = "./src/cv_test/capture.jpg")
{
    if (cap.isOpened())
    {
        cv::Mat frame;
        for (;;)
        {
            // capture image and display
            // cap.read(frame);
            cap >> frame;
            if (frame.empty())
                break;
            cv::imshow("camera 1", frame);

            // 
            char c = cv::waitKey(20);
            // std::cout<<(int)c<<std::endl;
            if (c == 'q')
            {
                // std::cout<<cv::getBuildInformation()<<std::endl;
                std::cout << "leave" << std::endl;
                // cap.release(); // release 后需断开并重新连接硬件
                break;
            }
            else if (c == 'c')
            {
                cv::imwrite(img_addr, frame);
                std::cout << "image saved to" + img_addr << std::endl;
            }
            else if (disp_props)
            {
                std::cout << "props: \nwidth, height: " << cap.get(cv::CAP_PROP_FRAME_WIDTH) << " " << cap.get(cv::CAP_PROP_FRAME_HEIGHT)
                          << "\nfps: " << cap.get(cv::CAP_PROP_FPS) << std::endl;
            }
        }
    }
}

void imgProc(cv::Mat dif){
     cv::Mat img_opened, img_closed, img_gradient, img_hat, img_blackhat;
    cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5,5), cv::Point(1,1));
    cv::morphologyEx(dif, img_opened, cv::MORPH_OPEN, element);
    cv::morphologyEx(dif, img_closed, cv::MORPH_CLOSE, element);
    cv::morphologyEx(dif, img_gradient, cv::MORPH_GRADIENT, element);
    cv::morphologyEx(dif, img_hat, cv::MORPH_TOPHAT, element);
    cv::morphologyEx(dif, img_blackhat, cv::MORPH_BLACKHAT, element);
    cv::namedWindow("origin",cv::WINDOW_FREERATIO);
    cv::namedWindow("open",cv::WINDOW_FREERATIO);
    cv::namedWindow("close",cv::WINDOW_FREERATIO);
    cv::namedWindow("gradient",cv::WINDOW_FREERATIO);
    cv::namedWindow("hat",cv::WINDOW_FREERATIO);
    cv::namedWindow("blackhat",cv::WINDOW_FREERATIO);
    cv::imshow("origin", dif);
    cv::imshow("open", img_opened);
    cv::imshow("close", img_closed);
    cv::imshow("gradient", img_gradient);
    cv::imshow("hat", img_hat);
    cv::imshow("blackhat", img_blackhat);
    for (;;)
    {
        if (cv::waitKey(10) == 27)
            break;
    }
    cv::destroyAllWindows();
}

int main(int argc, char **argv)
{
    // cv::String cameraID = "/dev/video1";
    // cv::namedWindow("camera 1", cv::WINDOW_FREERATIO);
    // cv::VideoCapture cap;
    // if (initCamera(cameraID, cap))
    // {
    //    dispVideo(cap, true);
    // }

    cv::Mat src1 = cv::imread("./src/cv_test/src1.jpg");
    cv::imshow("origin", src1);
    cv::Mat src2 = cv::imread("./src/cv_test/src2.jpg");
    cv::Mat sobel_x, sobel_y, sobel_scharr_x, sobel_scharr_y, manual, blend, blend_scharr;
    // cv::Mat kernel = (cv::Mat_<char>(3, 3) << -1, 0, 1,
    //                                         -2, 0, 2,
    //                                         -1, 0, 1);
    // cv::filter2D(src1, manual, src1.depth(), kernel);
    // cv::imshow("manual",manual);
    cv::Sobel(src1, sobel_x, src1.depth(),1,0);
    cv::imshow("sobel_x",sobel_x);
    cv::Sobel(src1, sobel_y, src1.depth(),0,1);
    // cv::imshow("sobel_y",sobel_y);
    cv::Sobel(src1, sobel_scharr_x, src1.depth(),1,0, CV_SCHARR);
    // cv::imshow("sobel_scharr_x",sobel_scharr_x);
    cv::Sobel(src1, sobel_scharr_y, src1.depth(),0,1, CV_SCHARR);
    // cv::imshow("sobel_scharr_y",sobel_scharr_y);

    cv::addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0.0, blend);//cv::cvtColor(blend, blend, cv::COLOR_BGR2GRAY);
    cv::addWeighted(sobel_scharr_x, 0.5, sobel_scharr_y, 0.5, 0.0, blend_scharr);//cv::cvtColor(blend_scharr, blend_scharr, cv::COLOR_BGR2GRAY);
    cv::threshold(blend, blend, 60, 255, cv::ThresholdTypes::THRESH_BINARY );
    cv::threshold(blend_scharr, blend_scharr, 60, 255, cv::ThresholdTypes::THRESH_BINARY );
    cv::imshow("blend", blend);
    cv::imshow("blend_scharr", blend_scharr);
    cv::waitKey();
    // cv::Mat diff2;
    // cv::absdiff(src1, src2, diff2);
    // imgProc(diff2);

    // std::cout<<cv::getBuildInformation()<<std::endl;
    // std::cout<<"leave"<<std::endl;
    return 0;
}