本站使用了 Pjax 等基于 JavaScript 的开发技术,但您的浏览器已禁用 JavaScript,请开启 JavaScript 以保证网站正常显示!

图像处理分析与机器视觉算法列表实现

封面.png

(1)距离变换

【距离变换】

  • 头文件
#pragma once

// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// distance transfer | 距离变换
// this is distance_transform.h

#include<opencv2/opencv.hpp>



namespace imageprocess
{
    // Distance transform function:距离变换函数
    void DistanceTransform(const cv::Mat& src_image, cv::Mat& dst_image);

    // Calculate City block distance: 计算城市街区距离
    int D4(const int& x1, const int& x2, const int& y1, const int& y2);

    // Calculate chessboard distance:计算棋盘距离
    int D8(const int& x1, const int& x2, const int& y1, const int& y2);

}//namespace imageproccess
  • 源文件


// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// distance transfer | 距离变换
// this is distance_transform.cpp

#include"distance_transfer.h"
#include<array>

void imageprocess::DistanceTransform(const cv::Mat& src_image, cv::Mat& dst_image)
{
    //step1: check the input parameters: 检查输入参数
    assert(!src_image.empty());
    assert(src_image.channels() == 1);

    //step2: initialize dst_image : 初始化目标图像
    cv::threshold(src_image, dst_image, 100, 255, cv::THRESH_BINARY);


    //step3: pass throuth from top to bottom, left to right: 从上到下,从做到右遍历
    for (size_t i = 1; i < dst_image.rows - 1; i++)
    {
        for (size_t j = 1; j < dst_image.cols; j++)
        {
            //AL  AL    
            //AL  P
            //AL
            std::array<cv::Point, 4> AL;
            AL.at(0) =  cv::Point( i - 1, j - 1 );
            AL.at(1) =  cv::Point( i - 1, j );
            AL.at(2) =  cv::Point( i, j - 1 );
            AL.at(3) =  cv::Point(i + 1, j - 1 );

            int Fp = dst_image.at<uchar>(i, j);

            //Fq
            std::array<int, 4> Fq = { 0 };
            Fq.at(0) = dst_image.at<uchar>(i - 1, j - 1);
            Fq.at(1) = dst_image.at<uchar>(i - 1, j);
            Fq.at(2) = dst_image.at<uchar>(i, j - 1);
            Fq.at(3) = dst_image.at<uchar>(i + 1, j - 1);

            std::array<int, 4> Dpq = { 0 };
            std::array<int, 4> DpqAddFq = { 0 };
        
            for (size_t k = 0; k < 4; k++)
            {
                //D(p, q)
                Dpq.at(k) = D4(i, AL.at(k).x, j, AL.at(k).y);
                //D(p,q) + F(q)
                DpqAddFq.at(k) = Dpq.at(k) + Fq.at(k);
            }
            //F(p) = min[F(p), D(p,q) + F(q)]
            std::sort(DpqAddFq.begin(), DpqAddFq.end());
            
            auto min = DpqAddFq.at(0);
            Fp = std::min(Fp, min);

            dst_image.at<uchar>(i, j) = Fp;

        }
    }

    
    //step4: pass throuth from bottom to top, right to left: 从下到上,从右到左遍历

    for (int i = dst_image.rows - 2; i > 0; i--)
    {
        for (int j = dst_image.cols -  2; j >= 0 ; j--)
        {
            //        BR
            //  P   BR
            //  BR  BR
            std::array<cv::Point, 4> BR;
            BR.at(0) = cv::Point( i - 1, j + 1 );
            BR.at(1) = cv::Point( i , j + 1 );
            BR.at(2) = cv::Point( i + 1, j + 1 );
            BR.at(3) = cv::Point( i + 1, j );

            int Fp = dst_image.at<uchar>(i, j);

            //Fq
            std::array<int, 4> Fq = { 0 };
            Fq.at(0) = dst_image.at<uchar>(i - 1, j + 1);
            Fq.at(1) = dst_image.at<uchar>(i, j + 1);
            Fq.at(2) = dst_image.at<uchar>(i + 1, j + 1);
            Fq.at(3) = dst_image.at<uchar>(i + 1, j);

            std::array<int, 4> Dpq = { 0 };
            std::array<int, 4> DpqAddFq = { 0 };

            for (size_t k = 0; k < 4; k++)
            {
                //D(p, q)
                Dpq.at(k) = D4(i, BR.at(k).x, j, BR.at(k).y);
                //D(p,q) + F(q)
                DpqAddFq.at(k) = Dpq.at(k) + Fq.at(k);
            }

            //F(p) = min[F(p), D(p,q) + F(q)]
            std::sort(DpqAddFq.begin(), DpqAddFq.end());

            auto min = DpqAddFq.at(0);
            Fp = std::min(Fp, min);

            dst_image.at<uchar>(i, j) = static_cast<uchar>(Fp);

        }
    }

    
}


int imageprocess::D4(const int& x1, const int& x2, const int& y1, const int& y2)
{
    return abs(x1 - x2) + abs(y1 - y2);
}

int imageprocess::D8(const int& x1, const int& x2, const int& y1, const int& y2)
{
    return cv::max(abs(x1 - x2), (y1 - y2));
}


  • 测试
// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// image proccess algorithm  | 图像处理算法
// this is main.cpp

#include"distance_transfer.h"



int main()
{
    cv::Mat src = cv::Mat::zeros(cv::Size(600, 400), CV_8UC1);

    for (size_t i = 100; i < 180; i++)
    {
        for (size_t j = 200; j < 400; j++)
        {
            src.at<uchar>(i, j) = 255;
        }
    }

    
    cv::Mat dst = src.clone();
    imageprocess::DistanceTransform(src, dst);
    normalize(dst, dst, 0, 255, cv::NORM_MINMAX);
    
    // opencv 
    /*cv::threshold(src, src, 100, 255, cv::THRESH_BINARY);
    cv::distanceTransform(src, dst, cv::DIST_L1, cv::DIST_MASK_PRECISE);
    normalize(dst, dst, 0, 1, cv::NORM_MINMAX);*/


    cv::imshow("src", src);
    cv::imshow("dst", dst);

    cv::imwrite("dst.jpg", dst);
    cv::waitKey(0);

    return 0;
}


(2)计算亮度直方图

【计算图像亮度直方图】

算法实现

  • 头文件
#pragma once
// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// gray histogram | 灰度直方图
// this is gray_histogram.h 

#include<opencv2/opencv.hpp>
#include<array>

namespace imageprocess
{
    // gray histogram 
    void GrayHistogram(const cv::Mat& gray_image, std::array<int, 256>& histogram);

    // histogram array to Mat
    void Histogram2Mat(const std::array<int, 256>& histogram, cv::Mat& histogram_mat);

}//namespace imageproccess
  • 源文件

// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// gray histogram | 灰度直方图
// this is gray_histogram.cpp

#include"gray_histogram.h"

void imageprocess::GrayHistogram(const cv::Mat& gray_image, std::array<int, 256>& histogram)
{
    // check the input parameter : 检查输入参数
    assert(gray_image.channels() == 1); 
    assert(histogram.size() == 256);

    // step1: All elements of the histogram array are assigned a value of 0 : 将数组histogram所有的元素赋值为0
    histogram = { 0 };

    // step2: Do hf[f(x,y)]+1 for all pixels of the image: 对图像所有元素,做hf[f(x,y)]+1
    for (size_t i = 0; i < gray_image.rows; i++)
    {
        for (size_t j = 0; j < gray_image.cols; j++)
        {
            int z = gray_image.at<uchar>(i, j);
            histogram.at(z) += 1;
        }
    }
}

void imageprocess::Histogram2Mat(const std::array<int, 256>& histogram, cv::Mat& histogram_mat)
{
    // Check the input parameter :检查输入参数
    assert(histogram.size() == 256);

    // step1: calculate the row of mat : 计算mat的row值
    int row = 0;
    for (size_t i = 0; i < histogram.size(); i++)
    {
        row = row > histogram.at(i) ? row : histogram.at(i);
    }
    
    // step2: initialize mat : 初始化mat
    histogram_mat = cv::Mat::zeros(row, 256, CV_8UC1);

    // step3: assign value for mat : 为mat赋值
    for (size_t i = 0; i < 256; i++)
    {
        int gray_level = histogram.at(i);

        if (gray_level > 0)
        {
            histogram_mat.col(i).rowRange(cv::Range(row - gray_level, row)) = 255;
        }
    }

    // step4: resize the histogram mat : 缩放直方图
    cv::resize(histogram_mat, histogram_mat, cv::Size(256, 256));
}

(3)产生加性零均值高斯噪声

【产生加性零均值高斯噪声】

  • 头文件
#pragma once

// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// gaussian_noise | 高斯噪声
// this is gaussian_noise.h

#include<opencv2/opencv.hpp>


namespace imageprocess
{
    void GaussionNoise(cv::Mat & image);

}//namespace imageproccess
  • 源文件
// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// gaussian_noise | 高斯噪声
// this is gaussian_noise.cpp

#include"gaussian_noise.h"
#include<cmath>
#include<random>
#include<ctime>

void imageprocess::GaussionNoise(cv::Mat & image)
{
    // step1: Check the input paramter :检出输入参数
    
    assert(!image.empty());
    assert(3 == image.channels());    // only color image

    // step2: Initialize the value of sigma :初始化sigma值
    double sigma = 1;

    // step3: Initialize 2 random numbers gamma、phi for every pixel: 针对初始化2两个随机数gamma、phi
    std::default_random_engine random(time(NULL));
    std::uniform_real_distribution<double> dis(0, std::nextafter(1, DBL_MAX));

    for (size_t i = 0; i < image.rows - 1; i++)
    {
        for (size_t j = 0; j < image.cols; j++)
        {
            double gamma = dis(random);
            double phi = dis(random);

            // step4: Compute the normal distribution by Box-Muller transfer:通过Box-Muller变换求解正态分布
            double z1 = sigma * std::cos(2 * 3.1415 * phi) * std::sqrt(-2 * log(gamma));
            double z2 = sigma * std::sin(2 * 3.1415 * phi) * std::sqrt(-2 * log(gamma));
            
            // step5: Add the gaussion noise to pixels: 添加噪声到像素点
            for (size_t k = 0; k < 3; k++)
            {
                double f1 = image.at<cv::Vec3b>(i, j)[k] + z1;
                double f2 = image.at<cv::Vec3b>(i + 1, j)[k] + z2;
                image.at<cv::Vec3b>(i, j)[k] = cv::saturate_cast<uchar>(f1);
                image.at<cv::Vec3b>(i + 1, j)[k] = cv::saturate_cast<uchar>(f2);
            }    
        }
    }    
}
  • 测试文件
// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// image proccess algorithm  | 图像处理算法
// this is main.cpp

#include"gaussian_noise.h"



int main()
{
    //cv::Mat src = cv::Mat(cv::Size(500, 300), CV_8UC3, cv::Scalar(200,200,200));

    cv::Mat src = cv::imread("./images/lena.jpg");
    
    imageprocess::GaussionNoise(src);

    cv::imshow("sigma=1", src);
    cv::waitKey(0);

    return 0;
}


(4)关系r的共生矩阵Cr(z,y)

灰度共生矩阵https://mangoroom.cn/opencv/gray-co-occurrence-matrix.html

  • 头文件
#pragma once
// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// co-occurrence matrix | 共生矩阵
// this is co-occurrence-matrix.h

#include<opencv2/opencv.hpp>

namespace imageprocess
{
    //*********calculate the co-occurrence matrix***************
    // image
    // offset x
    // offset y
    // co-occurrence matrix
    void GetCoOccUrrenceMatrix(const cv::Mat& image, int a, int b, std::vector<std::vector<double>> & cooccurrence_matrix);
}//namespace imageprocess
  • 源文件
// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// co-occurrence matrix | 共生矩阵
// this is co-occurrence-matrix.cpp

#include"co_occurrence_matrix.h"

//*********calculate the co-occurrence matrix***************
// image
// offset x
// offset y
// co-occurrence matrix
void imageprocess::GetCoOccUrrenceMatrix(const cv::Mat& image, int a, int b, std::vector<std::vector<double>> & cooccurrence_matrix)
{
    // only support gray image
    CV_Assert(image.channels() == 1);
    for (auto i = 0; i < image.rows; i++)
    {
        for (auto j = 0; j < image.cols; j++)
        {
            if (i + b >= image.rows || j + a >= image.cols)
            {
                continue;
            }
            int ij_valule = image.at<uchar>(i, j);
            int offet_ab_value = image.at<uchar>(i + b, j + a);
            cooccurrence_matrix[ij_valule][offet_ab_value] += 1;
        }
    }

    // normalize
    int sum = cooccurrence_matrix.size() * cooccurrence_matrix.at(0).size();
    for (auto i = 0; i < cooccurrence_matrix.size(); i++)
    {
        for (auto j = 0; j < cooccurrence_matrix.at(0).size(); j++)
        {
            cooccurrence_matrix[i][j] = cooccurrence_matrix[i][j] / sum;
        }
    }
}

(5)积分图像构建

详情阅读积分图像

// integral-image.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include<vector>

#include <opencv2/opencv.hpp>


int main()
{
    // load gray image
    cv::Mat image = cv::imread("lena.jpg", 0);
    if (image.empty())
    {
        return -1;
    }
    int row = image.rows;
    int col = image.cols;
    //---------- calculate the integral image---------

    // step1: initialize s(i, -1) =0;
    std::vector<std::vector<int> > s(row, std::vector<int>(col,0));

    // step2: initialize ii(-1, j) = 0;
    std::vector<std::vector<int> > ii(row, std::vector<int>(col, 0));


    // step3: calculate s(i,j) and ii(i,j)
    for (auto i = 0; i < row; i++)
    {
        for (auto j = 0; j < col; j++)
        {
            // s(i,j) = s(i,j -1) + f(i,j)
            if (j < 1)
            {
                s[i][j] = 0 + image.at<uchar>(i, j);//s(i, -1) =0;
            }
            else
            {
                s[i][j] = s[i][j - 1] + image.at<uchar>(i, j);
            }
            
            // ii(i,j) = ii(i-1, j) + s(i,j)
            if (i < 1)
            {
                ii[i][j] = 0 + s[i][j];//ii(-1, j) = 0;
            }
            else
            {
                ii[i][j] = ii[i - 1][j] + s[i][j];
            }
        }
    }


    // normalize and show the integral image
    double max = ii[row - 1][col - 1];
    cv::Mat integral_image = cv::Mat(cv::Size(col, row), CV_8UC1);
    for (auto i = 0; i < row; i++)
    {
        for (auto j = 0; j < col; j++)
        {
            ii[i][j] = int(double(ii[i][j] / max) * 255);
            integral_image.at<uchar>(i,j) = ii[i][j];
        }
    }

    cv::imshow("integral-image", integral_image);
    cv::waitKey(0);

    return 0;
}

(6)直方图均衡化

详情阅读直方图均衡化

// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// Histogram Equalization
// this is HistogramEqualization.cpp

#include <iostream>

#include<opencv2/opencv.hpp>
#include<array>

namespace imageprocess
{
    // gray histogram 
    void GrayHistogram(const cv::Mat& gray_image, std::array<int, 256>& histogram);

    // Histogram equalization
    void HistogramEqualization(const std::array<int, 256>& histogram, std::array<int, 256>& out, int pixels_cout);

    // histogram array to Mat
    void Histogram2Mat(const std::array<int, 256>& histogram, cv::Mat& histogram_mat);

}//namespace imageproccess

int main()
{
    cv::Mat src_image = cv::imread("Fig0222(a)(face).tif", cv::IMREAD_GRAYSCALE);

    if (src_image.empty())
    {
        return -1;
    }

    std::array<int, 256> histogram = { 0 };
    std::array<int, 256> new_histogram = { 0 };
    std::array<int, 256> dst_histogram = { 0 };

    imageprocess::GrayHistogram(src_image, histogram);

    cv::Mat histogram_mat;
    cv::Mat cdf;
    cv::Mat new_histogram_mat;
    cv::Mat dst_image = src_image.clone();
    imageprocess::HistogramEqualization(histogram, new_histogram, src_image.rows * src_image.cols);
    imageprocess::Histogram2Mat(histogram, histogram_mat);
    imageprocess::Histogram2Mat(new_histogram, cdf);

    // adjust the origin image pixels
    for (size_t i = 0; i < src_image.rows; i++)
    {
        for (size_t j = 0; j < src_image.cols; j++)
        {
            dst_image.at<uchar>(i, j) = new_histogram.at(src_image.at<uchar>(i, j));
        }
    }

    imageprocess::GrayHistogram(dst_image, dst_histogram);
    imageprocess::Histogram2Mat(dst_histogram, new_histogram_mat);

    cv::imshow("src-image", src_image);
    cv::imshow("dst-image", dst_image);
    cv::imshow("histogram", histogram_mat);
    cv::imshow("new-histogram", new_histogram_mat);
    cv::imshow("cdf", cdf);

    cv::imwrite("src-image.jpg", src_image);
    cv::imwrite("dst-image.jpg", dst_image);
    cv::imwrite("histogram.jpg", histogram_mat);
    cv::imwrite("new-histogram.jpg", new_histogram_mat);
    cv::imwrite("cdf.jpg", cdf);

    cv::waitKey(0);

    return 0;
}

void imageprocess::HistogramEqualization(const std::array<int, 256>& histogram, std::array<int, 256>& out, int pixels_cout)
{
    // check the input parameter
    assert(!histogram.empty() && !out.empty());

    // calculate the new histogram (cdf)
    out.at(0) = histogram.at(0);
    for (size_t i = 1; i < 256; i++)
    {
        out.at(i) = out.at(i - 1) + histogram.at(i);
    }

    // create the look up table
    for (size_t i = 0; i < 256; i++)
    {
        out.at(i) = static_cast<int>(255.0 * out.at(i) / pixels_cout);
    }
}


void imageprocess::GrayHistogram(const cv::Mat& gray_image, std::array<int, 256>& histogram)
{
    // check the input parameter : 检查输入参数
    assert(gray_image.channels() == 1);
    assert(histogram.size() == 256);

    // step1: All elements of the histogram array are assigned a value of 0 : 将数组histogram所有的元素赋值为0
    histogram = { 0 };

    // step2: Do hf[f(x,y)]+1 for all pixels of the image: 对图像所有元素,做hf[f(x,y)]+1
    for (size_t i = 0; i < gray_image.rows; i++)
    {
        for (size_t j = 0; j < gray_image.cols; j++)
        {
            int z = gray_image.at<uchar>(i, j);
            histogram.at(z) += 1;
        }
    }
}

void imageprocess::Histogram2Mat(const std::array<int, 256>& histogram, cv::Mat& histogram_mat)
{
    // Check the input parameter :检查输入参数
    assert(histogram.size() == 256);

    // step1: calculate the row of mat : 计算mat的row值
    int row = 0;
    for (size_t i = 0; i < histogram.size(); i++)
    {
        row = row > histogram.at(i) ? row : histogram.at(i);
    }

    // step2: initialize mat : 初始化mat
    histogram_mat = cv::Mat::zeros(row, 256, CV_8UC1);

    // step3: assign value for mat : 为mat赋值
    for (size_t i = 0; i < 256; i++)
    {
        int gray_level = histogram.at(i);

        if (gray_level > 0)
        {
            histogram_mat.col(i).rowRange(cv::Range(row - gray_level, row)) = 255;
        }
    }

    // step4: resize the histogram mat : 缩放直方图
    cv::resize(histogram_mat, histogram_mat, cv::Size(256, 256));
}

(7)使用旋转掩膜的平滑

(8)高效的中值滤波

(9)Canny边缘检测算子

(10)Harris角点检测器

(11)遍历极值区域

(12)基本的阈值化

(13)Ostu阈值检测法

(14)递归的多光谱阈值化

(15)有方向的边缘数据的非最大抑制

(16)边缘检测算子输出的滞后过滤

(17)内边界跟踪

(18)外边界跟踪

(19)扩展边界跟踪

(20)灰度图像中的边界跟踪

(21)图搜索 A-算法

(22)图像边界的启发式搜索

(23) 作为动态规划的边界跟踪

(24)使用hough变换的曲线检测

(25)广义huogh变换

(26)从部分边界形成区域

(27)区域归并(大纲)

(28)通过边界溶解的区域归并

(29)分裂与归并

(30)分裂并链接到分割树

(31)单程分裂与归并

(32)高效分水岭分割

(33)小图像区域消解

(34)基于匹配的分割

(35)均值位移模态检测

(36)均值位移不连续性保持滤波

(37)均值位移图像分割

(38)绝对模糊连接性分割

(39)模糊物体抽取

(40)有预设连接的模糊物体抽取

(41)图像分割

(42)最优表面分割

(43)多最优表面分割

(44)4领域和8领域标识

(45)在行程编码数据中的区域标识

(46)四叉树区域标识

(47)曲率估计--HK2003算法

(48)在四叉树中计算面积

(49)从Freeman 4连通链码表达中计算区域面积

(50)区域凸包构建

(51)简单多边形凸包检测

(52)通过细化提取并行骨架--MB算法

(53)通过细化提取并行骨架--MB2算法

(54)从骨架构建区域图

(55) 最小距离分类其的学习和分类

(56)使用K-D树的最近领域搜索

(57)在假定正太分布条件下基于概率密度估计的学习和分类

(58)支持向量机学习和分类

(59)K均值聚类分析

(60)反向传播学习

(61)Kohonen特征图的非监督学习

(62) 使用Hopfied网的识别

(63)句法识别

(64)图同构

(65)最大结查找

(66)遗传算法

(67)模拟退火优化

(68)模糊系统设计

(69)AdaBoost

(70)AdaBoost-MH

(71)自底向上控制

(72)冠状边界检测--一种混合控制策略

(73)非分层控制

(74)尺度不变特征变换

(75)利用随街抽样一致拟合模型--RANSAC

(76)相似训练形状的近似配准

(77)拟合ASM

(78)AAM构建

(79)活动表观模型匹配


本文由芒果浩明发布,转载请注明来源。
本文链接:https://mangoroom.cn/opencv/image-process-analysis-and-machine-vision-algorithm-examples.html


 继续浏览关于 opencv图像处理计算机视觉图像处理算法c++机器视觉 的文章

 本文最后更新于:2020/01/01 22:19:33,可能因经年累月而与现状有所差异

 引用转载请注明:芒果小屋 > opencv,算法,计算机视觉 > 图像处理分析与机器视觉算法列表实现