我是靠谱客的博主 无奈银耳汤,最近开发中收集的这篇文章主要介绍opencv mat 修改_(九)OpenCV中的数学运算(线性点运算),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

b199f2f3dc9ca76faf94de561ff54219.png

时间为友,记录点滴。

写点什么呢?这两天刚好把另一个专栏《数字图像处理》更新到了“数字图像处理中所用数学工具的介绍”,那不如这样吧,我们把这里面的例子,都用OpenCV来实现一下。

lowkeyway:第二章 数字图像基础-(六)数字图像处理中所用数学工具的介绍​zhuanlan.zhihu.com
6b3e3d268ab9e32207ad9ee3b83ea44f.png

先抄过来大纲:

  • 图像的像素级运算
点运算—— 线性点运算、非线性点运算
代数运算—— 加法、减法、乘法、除法
逻辑运算—— 求反、异或、或、与
  • 图像的空域变换
几何变换
非几何变换

恩,柿子挑软的捏,用我们已经讲过的知识加一点拓展来实现。

忽然发现如果我把所有的运算放到一片文章里,这篇文章就太长了,分开吧。本文先说线性点运算。

线性点操作

公式:

c7112c5e317dbd0ec4099620aabb9bfd.png
线性运算

那么它是如何跟图像对应的呢?

  • a=1, b=0: 恒等
  • a<0: 黑白翻转
  • |a|>1: 增加对比度
  • |a|<1: 减小对比度
  • b>0: 增加亮度
  • b<0: 减小亮度

好要求就这么多。

首先,我们要选择一张适合的照片,我是在OpenCv的github中挑了一张,因为它有黑白方格,很容易看到现象。

157531ac3b09c4331feef3d73fa029de.png
原图

图片来源:

opencv/opencv​github.com
939b0f5007dcc098f90a4c0cd2215ff3.png

C++版本:

注意点:

  1. 用saturate_cast修饰词来限制内存不越界。
  2. 用Vec3b来表示一个3个uchar组成的数组。
  3. 因为用的图是一个3通道的色彩图,所以取反的时候其实是用255减的。
  4. 如果做实验,只要修改linearTest函数的传参即可。
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;


static void showImgPara(Mat &img);
static void linearTest(string name, float a, float b);


int main()
{
	linearTest("left06.jpg", 0.5, 0);

	waitKey(0);
	return 0;
}


static void showImgPara(Mat &img)
{
	cout << "sizeof(img) is: " << sizeof(img) << ", img size is: " << img.size << endl;
	cout << "rows x cols: (" << img.rows << " x " << img.cols << ")" << endl;
	cout << "dims: " << img.dims << endl;
	cout << "channels: " << img.channels() << endl;
	cout << "type: " << img.type() << endl;
	cout << "depth:" << img.depth() << endl;
	cout << "elemSize:" << img.elemSize() << " (Bytes per element)" << endl;
	cout << "elemSize1:" << img.elemSize1() << "(Bytes per channel)" << endl;
	cout << "step[0]: " << img.step[0] << " (Bytes per cows only when 2 dims)" << endl;
	cout << "step[1]: " << img.step[1] << " (Bytes per element only when 2 dims)" << endl;
	cout << "step1(0): " << img.step1(0) << ", step1(1): " << img.step1(1) << " (step / elemSize1)" << endl;
}


static void linearTest(string name, float a, float b)
{
	/* Original Picture */
	Mat imgOri = imread(name);
	showImgPara(imgOri);
	namedWindow("original");
	imshow("original", imgOri);

	/* Output Picture */
	Mat imgOut = Mat::ones(imgOri.size(), imgOri.type());
	//namedWindow("zeros");
	//imshow("zeros", imgOut);

	uchar bOri = 0, gOri = 0, rOri = 0;

	for (int i = 0; i < imgOri.cols; i++)
	{
		for (int j = 0; j < imgOri.rows; j++)
		{
			bOri = imgOri.at<Vec3b>(j, i)[0];
			gOri = imgOri.at<Vec3b>(j, i)[1];
			rOri = imgOri.at<Vec3b>(j, i)[2];

			if (a >= 0)
			{
				imgOut.at<Vec3b>(j, i)[0] = saturate_cast<uchar>(a*bOri + b);
				imgOut.at<Vec3b>(j, i)[1] = saturate_cast<uchar>(a*gOri + b);
				imgOut.at<Vec3b>(j, i)[2] = saturate_cast<uchar>(a*rOri + b);
			}
			else
			{
				imgOut.at<Vec3b>(j, i)[0] = saturate_cast<uchar>(255 + a*bOri + b);
				imgOut.at<Vec3b>(j, i)[1] = saturate_cast<uchar>(255 + a*gOri + b);
				imgOut.at<Vec3b>(j, i)[2] = saturate_cast<uchar>(255 + a*rOri + b);
			}

		}
	}

	namedWindow("output");
	imshow("output", imgOut);
}

来看看结果吧

a=1, b=0: 恒等

6a91e593dd5ac6541a1444e94ddcf9c8.png
a=1;b=0
a<0: 黑白翻转

注意黑白方格,是刚好翻转的。

1e4ed314ee8b1e22af1aa3fcfd611ab5.png
a=-1;b=0
|a|>1: 增加对比度

62708ab1130f6c37100509876e2d2937.png
a=2;b=0
|a|<1: 减小对比度

9fc13464530e2e7823542a4bc665f88e.png
a=0.3;b=0
b>0: 增加亮度

f622f2e0bf4751bfe909cc8f441d709e.png
a=1;b=50
b<0: 减小亮度

eef30b8f8d59b2eaf4d505ef7e7f2f0e.png
a=1;b=-50

Python:

使用python就容易多了,感叹一下numpy的广播机制666

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:lowkeyway time:7/16/2019

import sys
import numpy as np
import cv2 as cv

def showImgPara(img):
    print("Sizeof img is: " + str(img.size))
    print("rows x cols is: " + str(np.size(img, 0)) + " x " + str(np.size(img, 1)))
    print("dimension is: ", img.ndim)
    print("dtype is: ", img.dtype)
    print("itemsize is: ", img.itemsize)
    print("shape is(rows, cols, depth): ", img.shape)

def linear(picName, a, b):
    #####################   Original Picture    #####################
    imgOri = cv.imread(picName)
    cv.namedWindow("imgOri")
    cv.imshow("imgOri", imgOri)
    showImgPara(imgOri)

    #####################   Output Picture    #####################
    imgOut = np.zeros(imgOri.shape, imgOri.dtype)

    if(a >= 0):
        imgOut = a * imgOri + b
    else:
        imgOut = 255 - (-a)*imgOri + b

    cv.namedWindow("imgOut")
    cv.imshow("imgOut", imgOut)


def main_func(argv):
    linear("left06.jpg", -1, 0)
    cv.waitKey(0)

if __name__ == '__main__':
    main_func(sys.argv)

结果输出跟C++一致,不贴了。

最后

以上就是无奈银耳汤为你收集整理的opencv mat 修改_(九)OpenCV中的数学运算(线性点运算)的全部内容,希望文章能够帮你解决opencv mat 修改_(九)OpenCV中的数学运算(线性点运算)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部