2019-05-16 19:22:40 qq_44091004 阅读数 244
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19563 人正在学习 去看看 夏曹俊

图像转灰

一幅完整的图像,是由红色、绿色、蓝色三个通道组成的。红色、绿色、蓝色三个通道的缩览图都是以灰度显示的。用不同的灰度色阶来表示“ 红,绿,蓝”在图像中的比重。通道中的纯白,代表了该色光在此处为最高亮度,亮度级别是255。
通道是整个Photoshop显示图像的基础。色彩的变动,实际上就是间接在对通道灰度图进行调整。通道是Photoshop处理图像的核心部分,所有的色彩调整工具都是围绕在这个核心周围使用的。
在计算机领域中,这类图像通常显示为从最暗黑色到最亮的白色的灰度,尽管理论上这个采样可以任何颜色的不同深浅,甚至可以是不同亮度上的不同颜色。灰度图像与黑白图像不同,在计算机图像领域中黑白图像只有黑色与白色两种颜色;灰度图像在黑色与白色之间还有许多级的颜色深度。但是,在数字图像领域之外,“黑白图像”也表示“灰度图像”,例如灰度的照片通常叫做“黑白照片”。在一些关于数字图像的文章中单色图像等同于灰度图像,在另外一些文章中又等同于黑白图像。
开发工具:eclipse、opencv.
准备工作:安装eclipse、下载opencv安装包,将其配置在eclipse中。
配置方法可参照官网:
图像转灰的方法是对图像像素值进行操作,将三通道三个像素各不相同的分量值赋值成相同的值,就实现了灰度变换。
灰度变换的方法有好几种:
1.浮点算法:Gray=R0.3+G0.59+B0.11
2.整数方法:Gray=(R
30+G59+B11)/100
3.移位方法:Gray =(R76+G151+B*28)>>8;
4.平均值法:Gray=(R+G+B)/3;
5.仅取绿色:Gray=G;
本文采用的是第四种方法,代码如下:

package com;
//转灰
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
public class ToGray {
	static {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);};
	public ToGray() {
		Mat source = Imgcodecs.imread("E://image//111.jpg");//读图片
		Mat dst = toGray(source);//调用转灰方法将结果保存在dst中
		Imgcodecs.imwrite("E://image//toGray1.jpg", dst);//将dst中的图片存在指定位置显示
	}

	Mat toGray(Mat source) {
		Mat dst = new Mat(source.size(), source.type());//获取图片的大小和类型
		for(int j = 0;j < source.height();j++) {
			for(int i = 0;i < source.width();i++) {
				double[] tmp = source.get(j, i);//获取图片像素值,注意这里的tmp是数组,存放的是该点rgb各分量值
				for(int k = 0;k < tmp.length;k++) {
					tmp[k] = (tmp[0]+tmp[1]+tmp[2])/3;//转灰,取三通道像素值和的平均值
				}
				dst.put(j, i, tmp);//将每一点的tmp值覆盖原来该点的像素值
			}
		}
		return dst;

	}

	public static void main(String[] args) {
		new ToGray();
	}

}


source
dst

2019-03-29 20:51:13 Tifa_Best 阅读数 213
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19563 人正在学习 去看看 夏曹俊

要求

  1. 利用 OpenCV 读取图像。
    具体内容:用打开 OpenCV 打开图像,并在窗口中显示
  2. 灰度图像二值化处理
    具体内容:设置并调整阈值对图像进行二值化处理。
  3. 灰度图像的对数变换
    具体内容:设置并调整 r 值对图像进行对数变换。
  4. 灰度图像的伽马变换
    具体内容:设置并调整γ值对图像进行伽马变换。
  5. 彩色图像的补色变换
    具体内容:对彩色图像进行补色变换。

过程

灰度变换

灰度变换的定义域和值域应该相等吧。

伽马变换: s=crγr[0,1]s=cr^\gamma \qquad r\in[0,1]

对数变换: s=clogv+1(1+vr)r[0,1]s=c\log_{v+1}(1+vr)\qquad r\in[0,1]

C++的functional库

整个处理流程大致相同,只有几个变换公式不同,所以把公共部分抽象出来成为一个函数,在每个变换中调用公共处理函数。

之前打算因为几个变换的函数实现中的参数个数不同,所以打算用bind的,后来发现lambda更简洁实用些。

function基本上代替了函数指针。

虽然花费了不少时间,但算是搞懂了function、bind和lambda的区别与用法。

代码

注意:补色被我理解成反色了,代码中的这个实现错误我也懒得改了。。。

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

#include <string>
#include <iostream>
#include <functional>

using namespace cv;
using namespace std;

void apply_LUT(Mat &src, Mat &dst, function<uchar(uchar)> pf)
{
    CV_Assert(src.depth() == CV_8U);

    Mat lookUpTable(1, 256, CV_8U);
    uchar* p = lookUpTable.ptr();
    for(int i = 0; i < 256; ++i)
        p[i] = pf(i);
    LUT(src, lookUpTable, dst);
    imshow("image", dst);
    waitKey(0);
}
void threshold_transform(Mat &src, Mat &dst, uchar thre)
{
    auto fun = [=](uchar r) -> uchar {return ((r > thre) ? 1 : 0) * 255;};
    apply_LUT(src, dst, fun);
}

// $s=cr^\gamma \qquad r\in[0,1]$
void gamma_transform(Mat &src, Mat &dst, float g=2, float c = 1.0)
{
    auto fun = [=](uchar r) -> uchar {return (c * pow(r/255., g)*255);};
    apply_LUT(src, dst, fun);
}

// $s=c\log_{v+1}(1+vr)\qquad r\in[0,1]$
void log_transform(Mat &src, Mat &dst, float v=1, float c=1)
{
    auto fun = [=](uchar r) -> uchar {
        return (c * 255. * log(1. + v*r/255.) / log(v + 1));};
    apply_LUT(src, dst, fun);
}

void inv_transform(Mat &src, Mat &dst)
{
    auto fun = [=](uchar r) -> uchar {return (255 - r);};
    apply_LUT(src, dst, fun);
}

int main (int argc, char **argv)
{
    String image_name((argc>1)?(argv[1]):("img_test.jpg"));
    Mat image, image_gray, image_dst;
    image = imread(image_name, IMREAD_COLOR);
    if (image.empty()) {
        cout << "Cannot read image: " << image_name << std::endl;
        return -1;
    }   
    cvtColor(image, image_gray, CV_BGR2GRAY);

    namedWindow("image", CV_WINDOW_AUTOSIZE);
    cout << "image origin" << endl;
    imshow("image", image);
    waitKey(0);

    cout << "image gray" << endl;
    imshow("image", image_gray);
    waitKey(0);

    cout << "image threshold" << endl;
    // threshold(image_gray, image_dst, 128, 255, THRESH_BINARY);
    threshold_transform(image_gray, image_dst, 128);

    cout << "image log" << endl;
    log_transform(image_gray, image_dst, 7);

    cout << "image gamma" << endl;
    gamma_transform(image_gray, image_dst, 9);

    cout << "image inv" << endl;
    inv_transform(image, image_dst);

    return 0;
}
2019-06-16 23:23:00 Geeksongs 阅读数 977
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19563 人正在学习 去看看 夏曹俊

数字图像处理:图像的灰度变换(Matlab实现)

(1)线性变换:
通过建立灰度映射来调整源图像的灰度。

k>1增强图像的对比度;k=1调节图像亮度,通过改变d值达到调节亮度目的;0

i = imread('theatre.jpg');
i = im2double(rgb2gray(i));
[m,n]=size(i);
%增加对比度
Fa = 1.25; Fb = 0;
O = Fa.*i + Fb/255;
figure(1), subplot(221), imshow(O);
title('Fa = 1.25, Fb = 0, contrast increasing');
figure(2),subplot(221), [H,x]=imhist(O, 64);
stem(x, (H/m/n), '.');
title('Fa = 1.25, Fb = 0, contrast increasing');
%减小对比度
Fa =0.5; Fb = 0;
O = Fa.*i + Fb/255;
figure(1), subplot(222),imshow(O);
title('Fa = 0.5, Fb = 0, contrast decreasing');
figure(2), subplot(222), [H,x] = imhist(O, 64);
stem(x, (H/m/n), '.');
title('Fa = 0.5, Fb = 0, contrast decreasing');
%线性亮度增加
Fa = 0.5; Fb = 50;
O = Fa.*i + Fb/255;
figure(1), subplot(223), imshow(O);
title('Fa = 0.5, Fb = 50, brightness control');
figure(2), subplot(223), [H,x]=imhist(O,64);
stem(x, (H/m/n), '.');
title('Fa = 0.5, Fb = 50, brightness control');
%反相显示
Fa = -1; Fb = 255;
O = Fa.*i + Fb/255;
figure(1), subplot(224), imshow(O);
title('Fa = -1, Fb = 255, reversal processing');
figure(2), subplot(224),[H,x]=imhist(O, 64);
stem(x, (H/m/n), '.');
title('Fa = -1, Fb = 255, reversal processing');

(2)对数变换:
增强低灰度,减弱高灰度值。

i = imread('theatre.jpg');


i = rgb2gray(i);
i = double(i);

out1 = log(1+i)/0.065;
out2 = log(1+i)/0.035;
out1(find(out1>255)) = 255;
out2(find(out2>255)) = 255;
out1 = uint8(out1);
out2 = uint8(out2);

(3)幂次变换:
次数小于1时,增强低灰度,减弱高灰度;次数大于1时增强高灰度,减弱低灰度。

i = rgb2gray(imread('theatre.jpg'));
i = double(i);
y1 = 255*(i/255).^2.5;
y2 = 255*(i/255).^0.4;
y1 = uint8(y1);
y2 = uint8(y2);

(4) 指数变换:
增强高灰度,减弱低灰度。

i = imread('theatre.jpg');
i = rgb2gray(i);
i = double(i);

y1 = 1.5.^(i*0.070)-1;
y2 = 1.5.^(i*0.050)-1;
y1(find(y1>255)) = 255;
y2(find(y2>255)) = 255;
y1 = uint8(y1);
y2 = uint8(y2);

(5)灰度拉伸:
有时图像灰度集中在某小块区域,需要改变图像对比度。

i = imread('theatre.jpg');
i = rgb2gray(i);
L = imadjust(i,[ ],[50/255;150/255]);
J = imadjust(L,[50/255;150/255 ],[20/255;230/255]);

(6)灰度均衡:
i = rgb2gray(imread('theatre.jpg'));
LC = imadjust(i,[ ],[50/255;150/255]);
HE1 = histeq(LC);%均衡函数

(7)直方图规定化:
实现局部的灰度均衡。

img = rgb2gray(imread('theatre.jpg'));
img_ref = rgb2gray(imread('rpic.jpg'));%参考图,按照这个的的直方图进行规定化
[hgram, x] = imhist(img_ref);
J = histeq(img, hgram);

posted @ 2019-06-16 23:23 Geeksongs 阅读(...) 评论(...) 编辑 收藏
2018-04-16 11:58:55 Ibelievesunshine 阅读数 5634
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19563 人正在学习 去看看 夏曹俊

空域内的图像增强就是调整灰度图像的明暗对比度,是对图像中各个像素的灰度值直接进行处理。

灰度变换增强是空域内对图像进行增强的一种简单而有效的方法。灰度变换增强不改变原图像中像素的位置,只改变像素点的灰度值,并逐点进行。为了进行灰度变换,首先要获取灰度图像的直方图。具体实现的代码如下:

close all;clear all;clc;
%获取灰度图像的直方图
I=imread('pout.tif');
row=size(I,1);  %图像的行
col=size(I,2);  %图像的列
N=zeros(1,256);  %创建1行256列的零矩阵
for i=1:row
    for j=1:col
        k=I(i,j);
        N(k+1)=N(k+1)+1;  %统计各个灰度值的像素数 灰度值范围0-255
    end
end
figure,
subplot(121),imshow(I);
subplot(122),bar(N);  %绘制直方图
axis tight;  %设置坐标轴

运行结果如下:

从图中可以看到,图像的灰度值主要集中在80-150之间,因此该图像比较模糊。我们可以通过将图像的灰度值均匀地分布在0-255之间,来将图像变得更加清晰。同时,需要将小于80的灰度值设置为0,大于150的灰度值设置为255。将原图像的灰度值设为x,增强图像的灰度值设为y,则得到以下关系:

化简后得:

接下来我们具体实现调整灰度图像的灰度范围,增强图像

close all;clear all;clc;
%调整灰度图像的灰度范围去增强图像
I=imread('pout.tif');
I=double(I);
J=(I-80)*255/70;  %具体调整方案
row=size(I,1);  %图像的行
col=size(I,2);  %图像的列
for i=1:row
    for j=1:col
        if(J(i,j)<0)  %灰度小于0像素的直接赋值为0
            J(i,j)=0;
        end
        if J(i,j)>255;  %灰度大于255的像素直接赋值为最大的255
            J(i,j)=255;
        end
    end
end
figure;
subplot(121),imshow(uint8(I));  %显示原始图像 显示时,修改图像的数据格式为uint8类型
subplot(122),imshow(uint8(J));  %显示增强结果

可以看到图片给人的感觉是清晰度显著增强。


------坚持下去,少年!------

2018-12-09 19:41:37 freehawkzk 阅读数 886
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19563 人正在学习 去看看 夏曹俊

图像灰度线性变换

1 概念

  灰度线性变换是一种灰度变换,通过建立灰度映射来调整源图像的灰度,达到图像增强的目的。灰度映射通常使用灰度变换曲线来表示。

2 原理

  灰度线性变换就是将图像的像素值通过指定的线性函数进行变换,以此增强或减弱图像的灰度。灰度线性变换的公式是常见的一维线性函数:
g(x,y)=kf(x,y)+b g(x,y) = k \cdot f(x,y) + b
xx为原始灰度值,则变换后的灰度值yy为:
y=kx+b(0y255) y = k \cdot x + b \dots\dots(0 \leq y \leq 255)
kk表示直线的斜率,即倾斜程度,bb表示线性函数在yy轴的截距。

3 作用

  

kk bb取值 意义
k&gt;1k&gt;1 增大图像的对比度,图像的像素值在变换后全部增大,整体效果被增强
k=1k=1 通过调整bb,实现对图像亮度的调整
0&lt;k&lt;10 &lt; k &lt; 1 图像的对比度被削弱
k&lt;0k&lt;0 原来图像亮的区域变暗,原来图像暗的区域变亮

4 Matlab实现

clc;
clear;
close all;

% 对灰度图进行灰度线性变换
ori_img = imread('../images/6.jpg');
ori_img = rgb2gray(ori_img);
[oriHist,oriX] = imhist(ori_img);

k = 1.25;
d = 0;
gray1 = ori_img * k + d;
[g1Hist,g1X] = imhist(gray1);

k = 1;
d = 50;
gray2 = ori_img * k + d;
[g2Hist,g2X] = imhist(gray2);

k = 0.5;
d = 0;
gray3 = ori_img * k + d;
[g3Hist,g3X] = imhist(gray3);

k = -1;
d = 255;
ori_ = im2double(ori_img);
gray4 = ori_ * k + 1.0;
[g4Hist,g4X] = imhist(gray4);

figure(1),subplot(1,2,1),imshow(ori_img),title('原图');subplot(1,2,2),imshow(gray1),title('k>0 d=0');
figure(2),subplot(1,2,1),stem(oriX,oriHist),title('原图直方图');subplot(1,2,2),stem(g1X,g1Hist),title('k>0 d=0直方图');
figure(3),subplot(1,2,1),imshow(ori_img),title('原图');subplot(1,2,2),imshow(gray2),title('k=1 d=50');
figure(4),subplot(1,2,1),stem(oriX,oriHist),title('原图直方图');subplot(1,2,2),stem(g2X,g2Hist),title('k=1 d=50直方图');
figure(5),subplot(1,2,1),imshow(ori_img),title('原图');subplot(1,2,2),imshow(gray3),title('k=0.5 d=0');
figure(6),subplot(1,2,1),stem(oriX,oriHist),title('原图直方图');subplot(1,2,2),stem(g3X,g3Hist),title('k=0.5 d=0直方图');
figure(7),subplot(1,2,1),imshow(ori_img),title('原图');subplot(1,2,2),imshow(gray4),title('k=-1 d=255');
figure(8),subplot(1,2,1),stem(oriX,oriHist),title('原图直方图');subplot(1,2,2),stem(g4X,g4Hist),title('k=-1 d=255直方图');

5 OpenCV实现

#include <iostream>
#include <string>

#include "../include/opencv400/opencv2/opencv.hpp"
#include "windows.h"

std::string g_CurrentDirectory;
void SetCurrentDirectoryToExePath()
{
	HMODULE hExe = GetModuleHandleA(NULL);
	char nameBuf[MAX_PATH] = { 0 };
	GetModuleFileNameA(hExe, nameBuf, MAX_PATH);
	std::string sName(nameBuf);
	sName = sName.substr(0, sName.rfind('\\'));
	SetCurrentDirectoryA(sName.c_str());
	g_CurrentDirectory = sName;
}


void calcHist1D(cv::Mat& input, cv::Mat& output)
{
	int channels[] = { 0 };
	int histsize[] = { 256 };
	float grayRnage[] = { 0,256 };
	const float* ranges[] = { grayRnage };
	cv::MatND hist;
	cv::calcHist(&input, 1, channels, cv::Mat(), hist, 1, histsize, ranges);

	double maxVal = 0;
	cv::minMaxLoc(hist, 0, &maxVal, 0, 0);

	int scale = 10;
	output = cv::Mat::zeros(500, 257 * 5, CV_8UC3);

	std::cout << "-----------------------------------" << std::endl;
	for (int i = 0; i < histsize[0]; i++)
	{
		float binVal = hist.at<float>(i, 0);
		std::cout <<i <<" "<< binVal << std::endl;
		int intensity = cvRound(binVal * 500 / maxVal);
		rectangle(output, cv::Point(i * 5, 500 - intensity),
			cv::Point((i + 1) * 5, 500),
			cv::Scalar::all(255),
			-1);
	}

}

int main()
{
	SetCurrentDirectoryToExePath();

	cv::Mat ori_img = cv::imread("../images/6.jpg");
	cv::Mat gray_img;
	cv::cvtColor(ori_img, gray_img, cv::COLOR_BGR2GRAY);
	//gray_img.convertTo(gray_img, CV_32FC1, 1.0 / 255);
	cv::namedWindow("灰度图");
	cv::imshow("灰度图", gray_img);

	cv::Mat grayHist;
	calcHist1D(gray_img, grayHist);
	cv::imshow("hist", grayHist);

	float k = 1.25;
	int d = 0;
	cv::Mat g1 = gray_img * k + d;
	cv::Mat g1Hist;
	calcHist1D(g1, g1Hist);
	cv::imshow("g1", g1);
	cv::imshow("g1Hist", g1Hist);

	k = 1;
	d = 30;
	cv::Mat g2 = gray_img * k + d;
	cv::Mat g2Hist;
	calcHist1D(g2, g2Hist);
	cv::imshow("g2", g2);
	cv::imshow("g2Hist", g2Hist);

	k = 0.5;
	d = 0;
	cv::Mat g3 = gray_img * k + d;
	cv::Mat g3Hist;
	calcHist1D(g3, g3Hist);
	cv::imshow("g3", g3);
	cv::imshow("g3Hist", g3Hist);

	k = -1;
	d = 255;
	cv::Mat g4 = gray_img * k + d;
	cv::Mat g4Hist;
	calcHist1D(g4, g4Hist);
	cv::imshow("g4", g4);
	cv::imshow("g4Hist", g4Hist);

	cv::waitKey();
	return 0;
}

6 效果图

原图
在这里插入图片描述

6.1 效果图

k> 1 b=0
在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述

7 讨论

线性变换是一个有限的查表操作,在C++实现时可以在将图像逐像素的计算过程转换为查表操作。由于灰度线性变换的查找表只需256字节,完全可以全部缓存到现代CPU的cache中,通过多线程的查表操作,可以加快整个图像的变换过程。当然,这样速度还是没有GPU中进行速度快。灰度线性变换是与相邻像素无关的操作,非常适合在GPU中并行计算。但需要根据图像大小,考虑图像从CPU到GPU再从GPU到CPU的时间损耗,时间加快只对很大的图有效。

没有更多推荐了,返回首页