精华内容
下载资源
问答
  • Opencv 线性混合操作的实现与API:addWeighted() 我有一个梦想,我写的代码,可以像诗一样优美。我有一个梦想,我做的设计,能恰到好处,既不过度,也无不足。 线性混合操作是像素级的操作,理论公式: g(x) =...

    Opencv 线性混合操作的实现与API:addWeighted()

    我有一个梦想,我写的代码,可以像诗一样优美。我有一个梦想,我做的设计,能恰到好处,既不过度,也无不足。

        线性混合操作是像素级的操作,理论公式:
    				  g(x) = (1 -a)f(x) + fa(x);
    
    /*@param src1 first input array.
    @param alpha weight of the first array elements.
    @param src2 second input array of the same size and channel number as src1.
    @param beta weight of the second array elements.
    @param gamma scalar added to each sum.
    @param dst output array that has the same size and number of channels as the input arrays.
    @param dtype optional depth of the output array; when both input arrays have the same depth, dtype
    can be set to -1, which will be equivalent to src1.depth().*/
    void addWeighted(InputArray src1, double alpha, InputArray src2,
                                  double beta, double gamma, OutputArray dst, int dtype = -1);
    

    简单介绍下参数:
    src1: 输入混合的第一个数组(图像);
    alpha: 第一个数组混合时所占的权重;
    src2: 输入混合的第二个数组,尺寸和通道数同一个相同。
    beta: 第二个数组的混合权重;
    gamma: 加在每个混合后的和上的标量值。
    dst: 混合后输出的数组,和输入的数组拥有相同的尺寸和通道数;
    dtype: 输出阵列的可选深度,默认-1,当两个数组深度相同,参数设为 -1;

    addWeighted()理论公式如下:
    dst = src1[i] * alpha + src2[i] * beta + gamma;

    好,到这理论就完了,下面开始看实现与对比:

    void MyAddWeighted()
    {
    	Mat mat(10, 10, CV_8UC1);
    	randu(mat, Scalar(0), Scalar(255));
    
    	Mat mat2(10, 10, CV_8UC1);
    	randu(mat2, Scalar(0), Scalar(255));
    
    	Mat dst;
    
       double alpha = 0.7, beta = 0.3, gamma = 0.;
    	/// mat rows cols == mat rows cols
    
    	CV_Assert(mat.type() == mat2.type() && mat.type() == CV_8UC1);
    	dst.create(10, 10, mat.type());
    	for (int i = 0; i < mat.rows; i++)
    	{
    		for (int j = 0; j < mat.cols; j++)
    		{
    			dst.at<uchar>(i, j) = cv::saturate_cast<uchar>(mat.at<uchar>(i, j) * alpha + mat2.at<uchar>(i, j) * beta + gamma);
    		}
    	}
    	cout << "dst = " << dst << endl;
    
    	Mat dst2;
    	addWeighted(mat, alpha, mat2, beta, gamma, dst2);
    	cout << "dst2 = " << dst2 << endl;
    	
    	Mat matTemp = dst - dst2;
    	cout << matTemp << endl;
    	Mat matTemp2 = dst2 - dst;
    	cout << matTemp2 << endl;
    }
    
    
    =========输出结果========
    
    dst = [ 93,  62, 115, 189,  60, 182, 225,  33, 177, 190;
      62, 228, 180, 155,  50, 162, 176, 120, 119,  78;
     154,  92, 160, 159, 155, 199, 167, 186, 171, 210;
     155, 187,  99,  77, 171, 206,  59,  78,  68, 192;
     198, 106, 198, 133,  52,  68,  18, 128, 190, 141;
     213,  84, 215,  93, 185,  75, 221,  69, 120, 121;
      81,  60, 102, 198, 171, 101, 162, 144,  57,  71;
     121, 116, 159,  88, 136,  32,  34, 220,  91,  82;
      18, 153, 183, 135, 189,  81, 107,  86,  98,  68;
     168,  88,  97, 124, 193, 112, 153, 216, 155, 250]
    dst2 = [ 93,  62, 115, 189,  60, 182, 225,  33, 177, 190;
      62, 228, 180, 155,  50, 162, 176, 120, 119,  78;
     154,  92, 160, 159, 155, 200, 167, 186, 171, 210;
     155, 187,  99,  77, 171, 206,  59,  78,  68, 192;
     198, 106, 198, 133,  52,  68,  18, 128, 190, 141;
     213,  84, 215,  93, 186,  75, 221,  69, 120, 121;
      81,  60, 102, 198, 171, 101, 162, 144,  57,  71;
     121, 116, 159,  88, 136,  32,  34, 220,  91,  82;
      18, 153, 183, 135, 189,  81, 107,  86,  98,  68;
     168,  88,  97, 124, 193, 112, 153, 216, 155, 250]
    [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0]
    [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   1,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   1,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0]
    
    

    可以看到,结果还是有点差异的,说明opencv在这个理论公式上还做了自己的一些细节上的处理,进入源码,跟了几层后发现下面一段代码:

    //以下代码按调用先后截取部分关键代码
    //片段1
    for (; x <= width - 4; x += 4)
    {
                T1 t0 = op::r(src1[x], src2[x], scalar);
                T1 t1 = op::r(src1[x + 1], src2[x + 1], scalar);
                dst[x] = t0; dst[x + 1] = t1;
    
                t0 = op::r(src1[x + 2], src2[x + 2], scalar);
                t1 = op::r(src1[x + 3], src2[x + 3], scalar);
                dst[x + 2] = t0; dst[x + 3] = t1;
    }
    
    //片段二
        static inline T1 r(T1 a, T1 b, const T2* scalars)
        { return c_add(a, b, scalars[0], scalars[1], scalars[2]); }
    //片段三    
    inline uchar c_add<uchar, float>(uchar a, uchar b, float alpha, float beta, float gamma)
    { return saturate_cast<uchar>(CV_8TO32F(a) * alpha + CV_8TO32F(b) * beta + gamma); }
    
    //片段四
    extern const float g_8x32fTab[];
    #define CV_8TO32F(x)  cv::g_8x32fTab[(x)+128]
    

    可以看到opencv中是把输入的像素值先经过CV_8TO32F(x)做了某种转化,在按照理论公式进行计算,至于CV_8TO32F(x)这个具体转化没能找到(-_-),有了解的评论区告诉我一下。
    不过这个也无伤大雅,知道原理有那么回事就行,毕竟也不会真的用自己实现的函数去做不是。

    注意:输出数组的深度为CV_32S时,此函数就不适应了,会造成内存溢出,或计算结果不正确(此句话取自毛星云opencv入门编程)。

    展开全文
  • OpenCV拉伸图像

    千次阅读 2017-05-13 22:15:10
    OpenCV的getPerspectiveTransform()函数 和 warpPerspective()函数配合使用,可以实现图像的拉伸。 下面给一个函数cvMatRect2Tetra(),将矩形图像拉伸成任意四边形。代码: #include "cvStretch.h" #pragma ...

    OpenCV的getPerspectiveTransform()函数 和  warpPerspective()函数配合使用,可以实现图像的拉伸。

    下面给一个函数cvMatRect2Tetra(),将矩形图像拉伸成任意四边形。代码:

    #include "cvStretch.h"
    
    #pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_core249d.lib")
    #pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_imgproc249d.lib")
    #pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_highgui249d.lib")
    #pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_ml249d.lib")
    #pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_video249d.lib")
    #pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_features2d249d.lib")
    #pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_calib3d249d.lib")
    #pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_objdetect249d.lib")
    #pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_contrib249d.lib")
    #pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_legacy249d.lib")
    #pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_flann249d.lib")
    
    
    cv::Mat cvMatRect2Tetra(cv::Mat mtxSrc, int iDstX1, int iDstY1, int iDstX2, int iDstY2,
    						int iDstX3, int iDstY3, int iDstX4, int iDstY4, int iDstWidth, int iDstHeight)
    {
    	cv::Mat mtxDst;
    	std::vector<cv::Point2f> src_corners(4);
    	std::vector<cv::Point2f> dst_corners(4);
    
    	src_corners[0]= cv::Point2f(0,0);
    	src_corners[1]= cv::Point2f(mtxSrc.cols - 1,0);
    	src_corners[2]= cv::Point2f(0, mtxSrc.rows - 1);
    	src_corners[3]= cv::Point2f(mtxSrc.cols - 1, mtxSrc.rows - 1);
    
    	dst_corners[0] = cv::Point2f(iDstX1, iDstY1);
    	dst_corners[1] = cv::Point2f(iDstX2, iDstY2);
    	dst_corners[2] = cv::Point2f(iDstX3, iDstY3);
    	dst_corners[3] = cv::Point2f(iDstX4, iDstY4);
    
    	cv::Mat transMtx = cv::getPerspectiveTransform(src_corners, dst_corners);
    	cv::warpPerspective(mtxSrc, mtxDst, transMtx, cv::Size(iDstWidth, iDstHeight));
    
    	return mtxDst;
    }
    拉伸之后,目标图仍是矩形,但是源图的左上角将对应目标图的(iDstX1, iDstY1), 右上角将对应目标图的(iDstX2, iDstY2);左下角将对应目标图的(iDstX3, iDstY3);右下角将对应目标图的(iDstX4, iDstY4).

    下面的实例调用函数cvMatRect2Tetra:

    #include "cvStretch.h"
    
    int main(void)
    {
    	cv::Mat cvSrc = cv::imread("E:\\lenaLeft.jpg");
    
    	cv::Mat cvDst = cvMatRect2Tetra(cvSrc, cvSrc.cols /4, 0, cvSrc.cols * 3 / 4, 0,
    		0, cvSrc.rows -1, cvSrc.cols - 1, cvSrc.rows - 1, cvSrc.cols - 1, cvSrc.rows - 1);
    
    	cv::namedWindow("Dst", CV_WINDOW_AUTOSIZE);
    	cv::imshow("Dst", cvDst);
    	
    	cv::waitKey();
      
       return 0; 
    }

    源图:


    目标图:


    对应不到的部分,程序自动用黑色填充。

    假如(iDstX, iDstY)的位置超过了目标图的尺寸,则超出部分被截掉。举个例子,把上面代码的目标左上、右上顶点坐标往上推500个像素,跑到目标图之外。

    int main(void)
    {
    	cv::Mat cvSrc = cv::imread("E:\\lenaLeft.jpg");
    
    	cv::Mat cvDst = cvMatRect2Tetra(cvSrc, cvSrc.cols /4, -500, cvSrc.cols * 3 / 4, -500,
    		0, cvSrc.rows -1, cvSrc.cols - 1, cvSrc.rows - 1, cvSrc.cols - 1, cvSrc.rows - 1);
    
    	cv::namedWindow("Dst", CV_WINDOW_AUTOSIZE);
    	cv::imshow("Dst", cvDst);
    	
    	cv::waitKey();
      
       return 0; 
    }

    结果:




    展开全文
  • 前些天本来打算用VC6.0 + opencv1.0去学习图像处理,但后来发现还是VS + opencv2以上...因为作业的要求,所以写了实现了灰度图像的直方均衡、线性变换与线性拉伸的程序。如果对上述几个概念不是很清楚可以参考下这篇
    前些天本来打算用VC6.0 + opencv1.0去学习图像处理,但后来发现还是VS + opencv2以上版本做比较顺手,所以装了vs2015,配置了环境什么的(
    VS2015配置opencv3.1.0)。在把环境配置好后,我就上网学习了
    别人写的代码,自己也开始写写简单的代码练手。因为作业的要求,所以写了实现了灰度图像的直方均衡、线性变换与线性拉伸的程序。如果对上述几个概念不是很清楚可以参考下
    这篇文章
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <iostream>
    
    using namespace std;
    using namespace cv;
    
    
    Mat XianChange(Mat &img, double alt, int base)//灰度线性变化、
    {
    	CV_Assert(img.depth() != sizeof(uchar));  //声明只对深度8bit的图像操作  
    	Mat temp = img.clone();
    
    	int channels = img.channels();            //获取图像channel  
    	int nrows = img.rows;                     //矩阵的行数  
    	int ncols = img.cols*channels;             //矩阵的总列数=列数*channel分量数  
    	if (img.isContinuous())               //判断矩阵是否连续,若连续,我们相当于只需要遍历一个一维数组  
    	{
    		ncols *= nrows;
    		nrows = 1;                 //一维数组  
    	}
    	//遍历像素点灰度值  
    	for (int i = 0; i<nrows; i++)
    	{
    		uchar *p = temp.ptr<uchar>(i);    //获取行地址  
    		for (int j = 0; j<ncols; j++)
    		{
    			p[j] = alt*p[j] + base;//修改灰度值  
    
    			if (p[j] > 255)
    				p[j] = 255;
    			if (p[j] < 0)
    				p[j] = 0;
    		}
    	}
    	return temp;
    }
    
    Mat XianStretch(Mat &img, int a, int b, int c, int d)//线性灰度拉伸,将[a,b]拉伸到[c,d]
    {
    	CV_Assert(img.depth() != sizeof(uchar));  //声明只对深度8bit的图像操作  
    	Mat temp = img.clone();
    
    	int channels = img.channels();            //获取图像channel  
    	int nrows = img.rows;                     //矩阵的行数  
    	int ncols = img.cols*channels;             //矩阵的总列数=列数*channel分量数  
    	if (img.isContinuous())               //判断矩阵是否连续,若连续,我们相当于只需要遍历一个一维数组  
    	{
    		ncols *= nrows;
    		nrows = 1;                 //一维数组  
    	}
    	//遍历像素点灰度值  
    	for (int i = 0; i<nrows; i++)
    	{
    		uchar *p = temp.ptr<uchar>(i);    //获取行地址  
    		for (int j = 0; j<ncols; j++)
    		{
    			if (p[j] < a)
    				p[j] = c / b * p[j];
    			else if (p[j] > a && p[j] < b)
    				p[j] = (d - c) / (b - a) * (p[j] - a) + c;
    			else
    				p[j] = (255 - d) / (255 - b) *(p[j] - b) + d;
    		}
    	}
    	return temp;
    }
    
    Mat HistogramEqu(Mat &img)               //直方均衡
    {
    	CV_Assert(img.depth() != sizeof(uchar));  //声明只对深度8bit的图像操作  
    	Mat temp = img.clone();
    	int grayNum[260] = { 0 };
    	int grayMap[260] = { 0 };
    
    	int channels = img.channels();            //获取图像channel  
    	int nrows = img.rows;                     //矩阵的行数  
    	int ncols = img.cols*channels;             //矩阵的总列数=列数*channel分量数  
    	int allPixel = nrows*ncols;               //图像的像素总数
    	int c;                                    //用于计算累积分布概率
    
    	if (img.isContinuous())               //判断矩阵是否连续,若连续,我们相当于只需要遍历一个一维数组  
    	{
    		ncols *= nrows;
    		nrows = 1;    //一维数组  
    	}
    	//遍历像素点灰度值  
    	for (int i = 0; i<nrows; i++)
    	{
    		uchar *p = temp.ptr<uchar>(i);    //获取行地址  
    		for (int j = 0; j<ncols; j++)
    		{
    			grayNum[p[j]]++;        //原图像的直方图
    		}
    	}
    
    	for (int i = 0; i < 256; i++)     //重新定义新的直方图
    	{
    		c = 0;
    		for (int j = 0; j<=i; j++)
    		{
    			c += grayNum[j];
    			grayMap[i] = int (255 * c / allPixel);
    			
    		}
    		//printf("%d %d\n", i, grayMap[i]);
    	}
    
    
    
    	for (int i = 0; i < nrows; i++)     //重新定义新的直方图
    	{
    		uchar *p = temp.ptr<uchar>(i);    //获取行地址  	
    		for (int j = 0; j < ncols; j++)
    		{
    			p[j] = grayMap[p[j]];
    		}
    	}
    	return temp;
    }
    
    int main()
    {
    	string picName = "lena256.jpg";
    	Mat A = imread(picName, CV_LOAD_IMAGE_GRAYSCALE);    //读入灰度图像  
    	
    	imshow("变换前", A);
    
    	Mat B = XianChange(A, 1, 20);//根据需要设置不同的参数
    	imshow("线性变换后", B);
    
    	Mat C = XianStretch(A, 10, 100, 20, 50);//根据需要设置不同的参数
    	imshow("线性拉伸后", C);
    
    	Mat D = HistogramEqu(A);
    	imshow("直方均衡后", D);
    
    	waitKey();
    	return 0;
    }

    程序运行完后的效果图:


    使用的原图:


    展开全文
  • import numpy as np from PIL import Image import matplotlib.pyplot as plt import matplotlib.cm as cm import scipy.signal as signal import cv2 as cv import random import easygui as g ...
    import numpy as np
    from PIL import Image
    import matplotlib.pyplot as plt
    import matplotlib.cm as cm
    import scipy.signal as signal
    import cv2 as cv
    import random
    import easygui as g
    import imutils
    import time
    
    class Point(object):
        def __init__(self,x,y):
            self.x = x
            self.y = y
        def getX(self):
            return self.x
        def getY(self):
            return self.y
    def criterion(p):  #定义我们自己种子生长的准则,p=1为一种规则,p=0为一种生长规则
        if p == 1:
            connect = [Point(-1,-1),Point(-1,0),Point(0,-1),Point(0,1),Point(1,1),Point(1,0),Point(-1,1),Point(1,-1)]
        else:
            connect = [Point(-1,0),Point(0,-1),Point(0,1),Point(1,0)]
        return connect
    def gray_distance(image,point1,point2):    #返回灰度值之间的差异,太大的我们舍弃
        return abs(int(image[point1.x,point1.y])-int(image[point2.x,point2.y]))
    def seed_growing(image):
        thresh = 3
        #我们自己设置的门限
        label1 = 1    #label = 1这样的话图像中为黑色,容易发现
        seed = [Point(250,100),Point(82,75),Point(20,300)]                #定义初始种子点
        image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
        image = image.astype(np.uint8)
        rows = image.shape[0]
        cols = image.shape[1]
        image_mark = np.full((rows,cols),255)
        seedlist = []
        p=1                 #定义我们自己的准则
        connects = criterion(p)
        for i in seed:
            seedlist.append(i)
        while ( len(seedlist) > 0):
            seed_testing = seedlist.pop(0)
            image_mark[seed_testing.x,seed_testing.y] = label1
            for i in range(8):   #因为我定义的P为1 所以是8个点,p=0则有四个点
                tempX = seed_testing.x + connects[i].x
                tempY = seed_testing.y + connects[i].y
                if tempX < 0 or tempY < 0 or tempX >=rows or tempY >= cols:
                    continue
                gray_dis = gray_distance(image,seed_testing,Point(tempX,tempY))
                if gray_dis < thresh and image_mark[tempX,tempY] == 255:
                    seedlist.append(Point(tempX,tempY))
                    image_mark[tempX,tempY] = label1
        cv.imshow('seed grow',image_mark.astype(np.uint8))
        cv.waitKey(0)
    
    
    def nothing(x):
        pass
    
    def change_number(image):
        image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
        image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
        rows = image.shape[0]
        cols = image.shape[1]
        min_area = 0
        max_area = 0
        area = rows * cols
        cv.namedWindow('could change threshhold')
        cv.createTrackbar('intensity', 'could change threshhold', 0, 255, nothing)
        count = 0
        # chance =0
        data1 = 699
        data = 0
        while (1):
            cv.imshow('could change threshhold', image) # 返回滑块所在位置对应的值
            medium_number = cv.getTrackbarPos('intensity', 'could change threshhold')
            # if chance == 0:
            image2 =image.copy()
            for i in range(rows):
                for j in range(cols):
                    if int(image2[i, j]) < medium_number:
                        image2[i, j] = 0
                        min_area += 1
                    else:
                        image2[i, j] = 255
                        max_area += 1
            image2 = image2.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
            cv.imshow('image2',image2)
            data +=1
            if data ==8:   #设置我们自己的时钟,按Q退出
                string = 'gray area is {},white area is {}'.format(min_area * area / (min_area + max_area),max_area * area / (min_area + max_area))
                print(string)
                data = 0
            # data +=1
            # if data == 2:
                # if data1 != medium_number:
                #     data1 = medium_number
                #     count = 0
                # else:
                #     count +=1
                #     if count == 2:
                        # image3 = image.copy()
                        # for i in range(rows):
                        #     for j in range(cols):
                        #         if int(image3[i, j]) < medium_number:
                        #             image3[i, j] = 0
                        #             min_area += 1
                        #         else:
                        #             image3[i, j] = 255
                        #             max_area += 1
                        # image3 = image3.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
                # string = 'gray area is {},white area is {}'.format(min_area * area / (min_area + max_area),max_area * area / (min_area + max_area))
                # print(string)
                # count =0
            # data = 0
            # chance +=1
            if cv.waitKey(1) == ord('q'):
                break
        cv.destroyAllWindows()
    
    
    def static_number(image):   #也进行灰度化
        image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
        image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
        rows = image.shape[0]
        cols = image.shape[1]
        sum2 = []
        for i in range(rows):
            for j in range(cols):
                sum2.append(int(image[i, j]))
        sum2.sort()
        medium_number = sum2[len(sum2)//2]     #去中位数的灰度值
        min_area = 0
        max_area = 0
        area = rows * cols
        for i in range(rows):
            for j in range(cols):
                if int(image[i,j]) < medium_number:
                    image[i,j] = 0
                    min_area +=1
                else:
                    image[i,j] = 255
                    max_area +=1
        image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
        g.msgbox('灰色区域面积为{0},白色面积为{1}'.format(min_area * area /(min_area+max_area),max_area * area/(min_area+max_area) ))
        cv.imshow('static number image',image)
        cv.waitKey(0)
    
    
    
    def myvar(image):   #将输入图片转换为灰度图
        image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
        image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
        rows = image.shape[0]
        cols = image.shape[1]
        sum1=[]
        for i in range(rows):
            for j in range(cols):
                sum1.append(int(image[i,j]))
        sum_average = sum(sum1)/len(sum1)
        var_sum=[]
        for i in range(rows):
            for j in range(cols):
                var_sum.append(image[i,j]**2/len(sum1))
        var = sum(var_sum) - sum_average**2
        return var
    
    
    
    def hist_stretch(image):     #没做灰度变换
        r_min, r_max = 255, 0
        a=[]
        for i in range(image.shape[0]):
            for j in range(image.shape[1]):
                for k in range(image.shape[2]):
                    a.append(image[i,j,k])
                    if image[i, j, k] > r_max:
                        r_max = image[i, j, k]
                    if image[i, j, k] < r_min:
                        r_min = image[i, j, k]
        a=np.array(a).reshape(-1)
        a_var=np.var(a)
        r1, s1 = r_min, 0
        r2, s2 = r_max, 255  # 这四个值决定了分段函数的走向
        # k1 = s1 / r1
        # k3 = (255 - s2) / (255 - r2)
        k2 = (s2 - s1) / (r2 - r1)     #255 * (最大灰度值-最小灰度值)
    
        b=[]
        precewise_img = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.float32)
        for i in range(image.shape[0]):
            for j in range(image.shape[1]):
                for k in range(image.shape[2]):
                    precewise_img[i, j, k] = k2 * (image[i, j, k] - r1)
                    b.append(precewise_img[i,j,k])
        b = np.array(b).reshape(-1,1)
        b_var = np.var(b)
        # g.msgbox('变换前的方差为{},变换后的方差为{}'.format(int(a),int(b)))
        print(a)
        print(b)
        # 原图中做分段线性变化后需要对图像进行归一化操作,并将数据类型转换到np.uint8
        cv.normalize(precewise_img, precewise_img, 0, 255, cv.NORM_MINMAX)
        precewise_img = cv.convertScaleAbs(precewise_img)
        g.msgbox('处理前的图片方差为{one},处理后的方差为{two}'.format(one=myvar(image), two=myvar(precewise_img)))
    
        cv.imshow('origin image', imutils.resize(image, 480))
        cv.imshow('hist_stretch image', imutils.resize(precewise_img, 480))
        if cv.waitKey(0) == 27:
            cv.destroyAllWindows()
    
    def muti_liner_stretch(image):                #s1,s2分别为灰度级上的两个边界,#该分段线性拉伸法,将灰度级分成三分,一份小于最小灰度级,一份大于最大灰度级,这两部分无定义,直接映射中间部分
        # r_min, r_max = 255, 0
        # for i in range(image.shape[0]):               #没做灰度变换
        #     for j in range(image.shape[1]):
        #         for k in range(image.shape[2]):
        #             if image[i, j, k] > r_max:
        #                 r_max = image[i, j, k]
        #             if image[i, j, k] < r_min:
        #                 r_min = image[i, j, k]
        r1, s1 = 50,100
        r2, s2 = 170,200      #这四个值决定了分段函数的走向
        k1 = s1 / r1
        k3 = (255 - s2) / (255 - r2)
        k2 = (s2 - s1) / (r2 - r1)
    
        precewise_img = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.float32)
        for i in range(image.shape[0]):
            for j in range(image.shape[1]):
                for k in range(image.shape[2]):
                    if r1 <= image[i, j, k] <= r2:
                        precewise_img[i, j, k] = k2 * (image[i, j, k] - r1)
                    elif image[i, j, k] < r1:
                        precewise_img[i, j, k] = k1 * image[i, j, k]
                    elif image[i, j, k] > r2:
                        precewise_img[i, j, k] = k3 * (image[i, j, k] - r2)
    
        # 原图中做分段线性变化后需要对图像进行归一化操作,并将数据类型转换到np.uint8
        cv.normalize(precewise_img, precewise_img, 0, 255, cv.NORM_MINMAX)
        precewise_img = cv.convertScaleAbs(precewise_img)
        g.msgbox('处理前的图片方差为{one},处理后的方差为{two}'.format(one=myvar(image),two=myvar(precewise_img)))    #函数本身没做灰度化,但是求方差时我做了灰度化
        cv.imshow('origin image', imutils.resize(image, 480))
        cv.imshow('muti_liner_stretch image', imutils.resize(precewise_img, 480))
        if cv.waitKey(0) == 27:
            cv.destroyAllWindows()
    def medium_filter(image):  #中值滤波模板为3*3
        image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
        image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
        # kernal_size=np.ones((3,3))
        rows=image.shape[0]
        cols = image.shape[1]
        gray_data = image.copy()
        img_new = []
        for i in range(rows-3):   #减去3的原因是自己定义的模板都是3*3
            line = []             #line记录着每一行的信息
            for j in range(cols-3):
                a = gray_data[i:i+3,j:j+3]  #此时类型a为np.uint8,转化为array类型方便后续计算
                a=np.array(a)
                a=np.sort(a.reshape(-1))
                line.append(a[4])   #np.multiply表示两个矩阵点乘
            img_new.append(line)   #记录着每一行卷积后的结果
        image2=np.array(img_new)
        image2 = (image2 / float(image2.max())) * 255
    
     # 显示图像
        plt.subplot(2,1,1)
        plt.title('original image')
        plt.imshow(image,cmap=cm.gray)
        plt.axis("off")
        plt.subplot(2,1,2)
        plt.title('after medium image')
        plt.imshow(image2,cmap=cm.gray)
        plt.axis("off")
        plt.show()
    
    def PepperandSalt(image,percentage):   # percentage表示噪声点出现的概率    #进来的第一步是灰度化
        # R = np.mat(image[:, :, 0])
        # G = np.mat(image[:, :, 1])
        # B = np.mat(image[:, :, 2])
        # img_gray2 = R * 0.299 + G * 0.587 + B * 0.114
        img_gray2 = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
        img_gray2 = img_gray2.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
        NoiseImg=img_gray2
        rows,cols=NoiseImg.shape
        NoiseNum=int(percentage*rows*cols)
        for i in range(NoiseNum):
            randX=np.random.randint(0,rows)
            randY=np.random.randint(0,cols)
            if random.randint(0,1) == 0:
                NoiseImg[randX,randY]=0
            else:
                NoiseImg[randX,randY]=255
        cv.imshow('Peppernoise image', NoiseImg)
        cv.waitKey(1000)
    
    def GaussianNoise(image,mean,sigma):     #mean表示均值,sigma表示方差    #第一步是灰度化
        # R=np.mat(image[:,:,0])
        # G=np.mat(image[:,:,1])
        # B=np.mat(image[:,:,2])
        # img_gray2 = R*0.299+G*0.587+B*0.114
        img_gray2 = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
        img_gray2 = img_gray2.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
        NoiseImg=img_gray2
        rows = NoiseImg.shape[0]
        cols = NoiseImg.shape[1]
        rows,cols=NoiseImg.shape
        for i in range(rows):
            for j in range(cols):
                NoiseImg[i,j]=NoiseImg[i,j]+random.gauss(mean,sigma)
        # NoiseImg = NoiseImg+np.random.normal(mean,sigma,NoiseImg.shape)
        # NoiseImg =  NoiseImg - np.full( NoiseImg.shape, np.min( NoiseImg))     # 全填充限定像素值下限(减去最小值,下限重新定义为0)
        # NoiseImg =  NoiseImg * 255 / np.max( NoiseImg)               #限定像素值上限
                if NoiseImg[i,j]<0:
                    NoiseImg[i,j] = 0
                elif NoiseImg[i,j]>255:
                    NoiseImg[i,j] = 255
        cv.imshow('guasenoise image', NoiseImg)
        cv.waitKey(1000)
    
    def salt(image1,number):      #number表述噪声点数量
        image = image1.copy()
        rows= image.shape[0]
        cols = image.shape[1]
        for i in range(number):
            x=np.random.randint(0,rows)   #np.ranom.randint 取不到右边界,ranodm.randint取得到右边界
            y=np.random.randint(0,cols)
            c=random.randint(0,1)
            if c == 1:
                image[x,y] = 255
            else:
                image[x,y] = 0
        return image
    def convolution(kernal_size, image):
        rows=image.shape[0]
        cols = image.shape[1]
        gray_data = image.copy()
        img_new = []
        for i in range(rows-3):   #减去3的原因是自己定义的模板都是3*3
            line = []             #line记录着每一行的信息
            for j in range(cols-3):
                a = gray_data[i:i+3,j:j+3]
                a=np.array(a)
                line.append(np.sum(np.multiply(kernal_size, a)))   #np.multiply表示两个矩阵点乘
            img_new.append(line)   #记录着每一行卷积后的结果
        return np.array(img_new)
    def mean_image(image):                  #均值滤波     #进来的第一不也是灰度化
        suanzi = np.ones((3,3))/9 # 创建全1算子(1/9)
        # 打开图像并转化成灰度图像
        image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
        image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
        image2 = convolution(image=image,kernal_size=suanzi)
        # 将结果灰度值转化到0-255
        image2 = (image2/float(image2.max()))*255
        image3=cv.blur(image,(5,5))
    
        # 显示图像
        plt.subplot(3,1,1)
        plt.title('original image')
        plt.imshow(image,cmap=cm.gray)
        plt.axis("off")
        plt.subplot(3,1,2)
        plt.title('after meaning image')
        plt.imshow(image2,cmap=cm.gray)
        plt.axis("off")
        plt.subplot(3, 1, 3)
        plt.title('function made')
        plt.imshow(image3, cmap=cm.gray)
        plt.axis("off")
        plt.show()
    def func(x,y,sigma=1):
        return 100*(1/(2*np.pi*sigma))*np.exp(-((x-1)**2+(y-1)**2)/(2.0*sigma**2))   #创建高斯函数,该函数中心为(1,1),所以创建3*3比较合适
    
    def gause_image(image):             #高斯滤波,第一步也实现了灰度化
        suanzi = np.fromfunction(func,(3,3),sigma=2)  # 创建高斯函数,(1,1)为函数的中心,这里是生成3*3的标准差为2的高斯算子
        # 打开图像并转化成灰度图像
        image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
        image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
        image2 = convolution(image=image, kernal_size=suanzi)
        # 将结果灰度值转化到0-255
        image2 = (image2 / float(image2.max())) * 255
    
        # 显示图像
        plt.subplot(2, 1, 1)
        plt.title('original image')
        plt.imshow(image, cmap=cm.gray)
        plt.axis("off")
        plt.subplot(2, 1, 2)
        plt.title('after gause image')
        plt.imshow(image2, cmap=cm.gray)
        plt.axis("off")
        plt.show()
    if __name__ == '__main__':
        # image1 = cv.imread('D:\\test.jpg')  #读取我们的照片
        # # image_salt = salt(image,2000)       #加入噪声
        # # mean_image(image_salt)
        # # gause_image(image_salt)
        # GaussianNoise(image1, mean=2, sigma=14)
        # cv.imshow('salt image', PepperandSalt(image1, percentage=0.01))
        msg = "请输入您想要完成的任务(建议您第一步先打开图片)"
        title = '第二次作业'
        choice = ('打开图片', '退出')
        a = g.buttonbox(msg=msg, title=title, choices=choice)
        if a == '打开图片':
            filename = g.fileopenbox(msg="请打开一个jpg文件")
            img = cv.imread(filename)
            msg1 = "选择您想要实现的功能"
            title1 = '第二次作业'
            choice1 = ('显示噪声图', '滤波', '阈值分割', '分段线性法拉伸', '直方图拉伸', '区域生长法分割','重新选择图片','退出')
            q = 1
            while q:
                b = g.buttonbox(msg=msg1, title=title1, choices=choice1)
                # while b!='退出':
                if b == '显示噪声图':
                    msg2 = "选择您想要实现的功能"
                    title2 = '第二次作业'
                    choice2 = ('灰色椒盐噪声图', '灰色高斯噪声图','退出')
                    q1=1
                    while q1:
                        noise_image_choice = g.buttonbox(msg=msg2, title=title2, choices=choice2)
                        if noise_image_choice == '灰色椒盐噪声图':
                            PepperandSalt(img, percentage=0.01) #这里设置椒盐噪声点出现的概率为0.01
                        elif noise_image_choice == '灰色高斯噪声图':
                            GaussianNoise(img, mean=2, sigma=14) #这里设置均值为2,方差为4
                        else:
                            q1 =0
    
                elif b == '滤波':
                    msg_b = "选择您想要实现的功能"
                    title_b = '第二次作业'
                    choice_b = ('均值滤波', '高斯滤波','中值滤波')
                    q_b = 1
                    while q_b:
                        b_remove_noise = g.buttonbox(msg=msg_b, title=title_b, choices=choice_b)
                        if b_remove_noise == '均值滤波':
                            mean_image(salt(img,number=5000))          #salt为自己定义的可以随意增加噪声点的函数,number为自己定义噪声点的数量
                        elif b_remove_noise =='高斯滤波':
                            gause_image(salt(img,number=5000))
                        elif b_remove_noise == '中值滤波':
                            medium_filter(salt(img,number=5000))
                        else:
                            q_b = 0
    
                elif b == '阈值分割':
                    msg_b1 = "选择您想要实现的功能"
                    title_b1 = '第二次作业'
                    choice_b1 = ('固定阈值', '调节参数窗')
                    q_b1 = 1
                    while q_b1:
                        b_remove_noise1 = g.buttonbox(msg=msg_b1, title=title_b1, choices=choice_b1)
                        if b_remove_noise1 == '固定阈值':
                            static_number(img)
                        elif b_remove_noise1 == '调节参数窗':
                            change_number(img)
                        else:
                            q_b1 = 0
    
                elif b == '分段线性法拉伸':
                    muti_liner_stretch(img)
                elif b == '直方图拉伸':
                    hist_stretch(img)
                elif b == '区域生长法分割':
                    seed_growing(img)
                elif b == '重新选择图片':
                    filename = g.fileopenbox(msg="请打开一个jpg文件")
                    img = cv.imread(filename)
                else:
                    q = 0
    ```python
    在这里插入代码片
    
    
    
    展开全文
  • 这段程序是对灰度图像进行非线性拉伸,即讲灰度图像的灰度分段,分为三段,低灰度级,中灰度级,高灰度级,把三段灰度级进行灰度压缩,使得亮的地方更亮,暗的地方更暗,这样可以增加灰度的对比度,便于目标跟踪。
  • 实验内容及实验原理:html一、灰度的线性变换node灰度的线性变换就是将图像中全部的点的灰度按照线性灰度变换函数进行变换。该线性灰度变换函数是一个一维线性函数:f(x)=a*...函数二、灰度拉伸post灰度拉伸和灰度线...
  • opencv线性坐标映射

    2020-08-21 09:57:34
    传统的仿射变换是均匀拉伸,可以将目标拉伸到一定的尺寸,但图像不同位置的拉伸尺度却不相同,所以需要再次对图像做一次坐标映射。 voidremap(InputArraysrc,OutputArraydst, InputArraymap1,InputArraymap2, int...
  • 实验内容及实验原理:1、灰度的线性变换灰度的线性变换就是将图像中所有的点的灰度按照线性灰度变换函数进行变换。该线性灰度变换函数是一个...2、灰度拉伸灰度拉伸和灰度线性变换相似。不同之处在于它是分段线性变...
  • 1、算法原理 分段线性拉伸算法是图像灰度变换中常用的算法,在商业图像编辑软件Photoshop中也有相应的功能。分段线性拉伸主要是用于提高图像对比度,突显图像细节。设输入图像为f(x),输出图像为f'(x),分段区间为...
  • 1.公式1.1线性变换假设原图像 f(x,y)的灰度范围为[a,b],希望变换后图像 g(x,y)的灰度范围扩展至[c,d],则灰度线性变换可表示为 1.2分段线性变换 2.C++代码实现#include "cv.h" #include "highgui.h" #include ...
  • 仿射变换-基于2x3矩阵进行的图像变换 ...在OpenCV里,代表这种变换的标准形式是2x3矩阵。 ###################################################### 稠密仿射变换 void cvWarpAffine( const CvArr* src, CvArr* d
  • (3), 根据线性公式,求拉伸后灰度值,如下图1. matlab代码:%题目: 对比度拉伸 %意义:所期望观察的对象因对比度不足而不够清晰,需进行对比度拉伸。 %灰度值的分段线性映射 %已知条件:原图像的目标景物灰度...
  • opencv2/core.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <iostream> #include <math.h> using namespace cv; Mat Judge(Mat input, int h, int ...
  • 线性对比度增强——最大-最小值对比度拉伸,使用gdal读取img格式文件,并进行对比度拉伸。注意配置好相关路径
  • 本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的、不同方法的处理,以达到对图像进行去噪、锐化等一系列的操作。...
  • Python OpenCV实例:图像灰度拉伸

    千次阅读 2018-04-19 17:13:00
    定义:灰度拉伸,也称对比度拉伸,是一种简单的线性点运算。作用:扩展图像的 直方图,使其充满整个灰度等级范围内 公式: g(x,y) = 255 / (B - A) * [f(x,y) - A], 其中,A = min[f(x,y)],最...
  • OpenCV学习笔记(一)对比度拉伸

    万次阅读 2016-12-06 14:27:42
    分段线性线性变换的分段形式,分段线性中的各个函数是任意设定的。分段线性能够实现对图像某些区域的特定分析,常用于图像增强中。最简单的就是对比度拉伸。  对比度拉伸技术是通过扩展图像灰度级动态范围来实现...
  • 一、图像线性混合 1、原理及函数介绍 2、代码 3、图像 二、亮度和对比度增强 1、概念(亮度和对比度) 2、原理 3、单通道处理(灰度图) 代码: 效果: 4、多通道处理(彩图) 代码: 效果: 5、代码 ...
  • # coding:utf-8 ...灰度图像线性运算 公式:g(x,y) = p * f(x,y) + L 其中:f(x,y)为输入灰度图像像素值,g(x,y)为输出灰度图像像素值 参数:p = 1,L = 0,则复制图像; p > 1,则图像对比度减少 p =...
  • 模糊原理 Smooth/Blur 是图像处理中最简单和常用的操作之一 ...通常这些卷积算子计算都是线性操作,所以又叫线性滤波 举个例子 这个是均值滤波今天我们这里学习两个滤波: 归一化框过滤器(均值滤波) 高...
  • OpenCV图像增强之对比度拉伸 C++

    千次阅读 2019-02-19 17:51:22
    下图是典型的对比度拉伸变换。点(r1,s1)和(r2,s2)的位置控制变换函数的形状。 如果r1=r2,s1=s2,则变换为一线性函数; 若r1=r2,s1=0且s2=L-1,则是阈值处理函数,产生一幅二值图像; 处理一幅8bit低对比度图像,(r1,...
  • OpenCV与图像处理学习五——图像基本操作(下)三、图像滤波与增强3.1 线性滤波3.1.1 方框滤波 上两次的笔记地址: OpenCV与图像处理学习三——图像基本操作(上) OpenCV与图像处理学习四——图像基本操作(中) ...
  • OpenCv图像处理之亮度与对比度的调整对比度亮度使用cv::saturate_cast<>()进行线性变换 对比度 差异范围越大代表对比越大,差异范围越小代表对比越小,好的对比率120:1就可容易地显示生动、丰富的色彩,当对比...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,119
精华内容 447
关键字:

opencv线性拉伸