• opencvLUT查表


    从数学上来看查找表是一个简单的一对一或多对一的函数,定义了如何将像素转换为新的值。从数据的组织关系上来看,查找表是一维或多维的数组,存储了不同输入值所对应的输出值。数据表在图像处理中主要用于像素的点运算,尤其是像素之间无位置相关性的操作中。比如求图像镜像变换的示例就很难运用查找表的方法来实现。而在颜色缩减、图片取反以及直方图均衡化等不涉及像素位置相关性的算法中我们都可以应用。当然,查找表的优势也很明显[大巧于内],只需读取、无需计算

    查表实例说明:

    1.颜色空间缩减:将现有颜色空间值除以某个输入值,以获得较少的颜色数。例如,颜色值0到9可取为新值0,10到19可取为10,以此类推。(示例来源于OpenCV官网)。

    显然这是一个多对一的映射,I[new] = I[old]/10*10。很容易想到,只要遍历图像矩阵的每一个像素,对像素应用上述公式就可以完成任务。只是这里用到了除法和乘法运算,而这两种运算又特别费时。鉴于一幅图像只涉及256个像素,我们大可开一个长度为256的数组,让其下标代表旧像素值,数组值代表新的像素值,如lookup[256]={0,…,0,10,…,10,20,…,20,…,250,…,250}。这样我们遍历修改时不就可以通过像素值从表中查出要改变的像素值了么,而且这一过程只有赋值运算。

    2.图像取反:反转图像的像素强度,使图像中的前景变为背景,背景变为前景。

    显然这是一个一对一的映射,即像素值0变为255,1变为254…254变为1,255变为0。对应的查找表为lookup[256]={255,254,…,1,0}

    不使用LUT查表函数的程序

    #include<opencv2/opencv.hpp>
    #include<iostream>
    #include  <vector>
    
    void Invert(cv::Mat& img, uchar* lookup) {  //取反函数
        int rows = img.rows;
        int cols = img.cols;
        int k = 0;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                int k = img.at<uchar>(i, j);
                img.at<uchar>(i, j) = *(lookup+k);
            }
        }
    }
    
    int main(int argc, char** argv) {
    
        cv::Mat src = cv::imread("D:/bb/tu/ma1.png",0);
        cv::imshow("修改前", src);
    
        //建立查找表
        uchar lookup[256];
        for (int i = 0; i < 256; i++) {
            lookup[i] = 255 - i;
        }
    
        Invert(src, lookup);
    
        cv::imshow("修改后", src);
        
        cv::waitKey(0);
        return 0;
    }

    使用LUT查表函数的程序 

    方式一

    #include<opencv2/opencv.hpp>
    #include<iostream>
    #include  <vector>
    
    
    int main(int argc, char** argv) {
    
        cv::Mat src = cv::imread("D:/bb/tu/ma1.png",0);
        
    
        cv::Mat lookUpTable(1, 256, CV_8U); //创建表矩阵
        uchar* p = lookUpTable.data;  //让指针p指向表矩阵的数据地址
        for (int i = 0; i < 256; ++i)  p[i] = 255 - i;//给表矩阵赋值
    
        cv::Mat dst;
        cv::LUT(src, lookUpTable, dst);//查表
        //第一个参数:原始图像的地址
        
        //第二个参数:查找表的地址;查找表也可以是单通道,也可以是3通道,如果输入图像为单通道,
        //那查找表必须为单通道,若输入图像为3通道,查找表可以为单通道,也可以为3通道,
        //若为单通道则表示对图像3个通道都应用这个表,若为3通道则分别应用
    
        //第三个参数:输出图像的地址
    
        cv::imshow("修改前", src);
        cv::imshow("修改后", dst);
        
        cv::waitKey(0);
        return 0;
    }

    方式二

    #include<opencv2/opencv.hpp>
    #include<iostream>
    #include  <vector>
    
    
    int main(int argc, char** argv) {
    
        cv::Mat src = cv::imread("D:/bb/tu/ma1.png",0);
        
        uchar lookup[256];
        for (int i = 0; i < 256; i++) {
            lookup[i] = 255 - i;
        }
        cv::Mat lut(1, 256, CV_8UC1, lookup);//创建表矩阵
    
        cv::Mat dst;
        cv::LUT(src, lut, dst);
    
    
        cv::imshow("修改前", src);
        cv::imshow("修改后", dst);
        
        cv::waitKey(0);
        return 0;
    }

  • 相关阅读:
    SharePoint:扩展DVWP 第33部分:修改DVWP中的合计和分类汇总
    通过SharePoint Web服务更新审批状态
    SharePoint:扩展DVWP 第29部分:修改Remove模版上的表单操作工作流
    SharePoint:扩展DVWP 第27部分:为DVWP添加一个备用编辑模版
    SharePoint 2010之Visio Services入门1-2-3
    一步一步开发属于自己的SharePoint 2010工作流
    在SharePoint 2010中创建自定义字段类型
    SharePoint:扩展DVWP 第25部分:通过SPServices创建列表项实现审计跟踪
    欢迎参加天津PDC Party的活动
    SharePoint:扩展DVWP 赠送部分:当“找不到匹配项”时修复Insert表单操作
  • 原文地址:https://www.cnblogs.com/liming19680104/p/15592980.html
Copyright © 2020-2023  润新知