看下实现效果
准备工作我们需要导入webcam包
## 视频图像获取:
http://webcam-capture.sarxos.pl/
## 导包:
- Eclipse :
- * 项目:
- 1: 右键项目名 Build Path - Config BuildPath - Lib - add Jars 选中
- IDEA :
- 1:右键项目名 Module Setting
- 2:找到 lib -> +号 Java 选中jar包
实现代码
1videoui类
public class VideoUI extends JFrame {
public VideoUI(){
setTitle("图像处理");
setSize(1000,1000);
setDefaultCloseOperation(3);
//设置流式布局
setLayout(new FlowLayout());
VideoListener vl = new VideoListener();
addButton (vl);
setVisible(true);
//摄像头
/*只有一个时: */
Webcam webcam = Webcam.getDefault();
webcam.setViewSize(WebcamResolution.VGA.getSize());
webcam.open();
PlayVideo playVideo = new PlayVideo();
//得将playVIdeo 传到监听器当中去
vl.playVideo = playVideo;
//这是死循环,之后不能再写代码
playVideo.runVideo(webcam,getGraphics());
//后面不能加代码
}
public void addButton(VideoListener vl){
// 先定义一个字符串数组 存储所有按钮的字符串
String[] btnstrs = {
"原图","马赛克","刷新图片", "反片", "脸部提亮", "灰度", "二值化", "美白", "油画", "轮廓提取", "撤回","暖色系","冷色系","珠纹化"
};
for(int i = 0; i < btnstrs.length; i++){
String btnstr = btnstrs[i];
JButton btn = new JButton (btnstr);
add (btn);
// 按钮添加监听器
btn.addActionListener (vl);
}
}
public static void main(String[] args) {
new VideoUI();
}
}
2videolistener类
public class VideoListener implements ActionListener {
PlayVideo playVideo;
@Override
public void actionPerformed(ActionEvent e) {
String btnstr = e.getActionCommand();
//点击按钮之后,修改死循环中的判断所用到的变量的值
playVideo.btnstr=btnstr;
System.out.println("点击了"+btnstr);
}
}
3playvideo类
public class PlayVideo {
//定义一个属性 按钮文本
String btnstr=""; //得给一个默认值,不然提示报错为空;
//VideoEff 视频效果对象imageEff
VideoEff imageEff = new VideoEff();
/*
*播放视频
*/
public void runVideo(Webcam webcam, Graphics g){
//用死循环来一帧一帧处理图片
while (true){
//1、获取图片
BufferedImage img = webcam.getImage();
int [][]imagePixArray = imageEff.getImagePixArray(img);
//2、判断如何处理图片
if(btnstr.equals("原图")){
//不需要处理
g.drawImage(img,100,100,null);
}
if(btnstr.equals("马赛克")){
//传入图像数组,图片对象,视频效果对象调用该类中的方法来绘制
imageEff.drawImage_02(imagePixArray,g);
}
if(btnstr.equals ("反片")){
imageEff.drawImage_03(imagePixArray,g);
}
if(btnstr.equals ("脸部提亮")){
imageEff.drawImage_04(imagePixArray,g);
}
if(btnstr.equals ("灰度")){
imageEff.drawImage_05(imagePixArray,g);
}
if(btnstr.equals ("二值化")){
imageEff.drawImage_06(imagePixArray,g);
}
if(btnstr.equals ("油画")){
imageEff.drawImage_08(imagePixArray,g);
}
if(btnstr.equals ("轮廓提取")){
imageEff.drawImage_09(imagePixArray,g);
}
if(btnstr.equals("珠纹化")) {
imageEff.drawImage_13(imagePixArray,g);
}
}
}
}
4videoeff类
public class VideoEff {
//图片绘制坐标的参数
final int X=100;
final int Y=100;
/**
* 将一张图片转为二位数
*
* @param buffimg
* 缓冲图片对象
* @return 存有图片像素值的二维数组
*/
public int[][] getImagePixArray(BufferedImage buffimg) {
// 获取图片尺寸
int w=buffimg.getWidth();
int h=buffimg.getHeight();
//创建新的二维数组来保存图片信息
int [][]imgarr=new int[w][h];
for(int i=0;i<w;i++) {
for(int j=0;j<h;j++) {
imgarr[i][j]=buffimg.getRGB(i,j);
}
}
//返回图片数组
return imgarr;
}
//————————————————————————————————————————————————————————————————————————————————————
//以下是绘制图片效果部分
/**
* 1、绘制原图方法
* @param imgarr 图片数组
* @param g 图像画笔对象
*/
public BufferedImage drawImage_01(int[][] imgarr,Graphics g) {
BufferedImage img = new BufferedImage(imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
// 如何不绘制特殊形状, 可以考虑直接设置RGB
for(int i=0;i<imgarr.length;i++) {
for(int j=0;j<imgarr[i].length;j++) {
int rgb = imgarr[i][j];
//将RGB 遍历存入BufferedImage;
img.setRGB(i,j,rgb);
}
}
g.drawImage(img,X,Y,null);
return img;
}
* 2、马赛克:每隔几个点取几个像素,并将图像放大 只需要在原图基础上设置取点位置以及放大g的宽和高
* @param imgarr 图片数组
* @param g 图像画笔对象
*/
public BufferedImage drawImage_02(int[][] imgarr,Graphics g) {
BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
//获取缓冲区画
// g = img.getGraphics();
for(int i=0;i<imgarr.length;i+=10) {
for(int j=0;j<imgarr[i].length;j+=10) {
int rgb = imgarr[i][j];
Color color =new Color(rgb);
g.setColor(color);
g.fillRect(X+i,Y+j,10,10);
}
}
g.drawImage(img,X,Y,null);
return img;
}
/**
* 3、反片 利用获取颜色255-red,255-green,255-blue来做处理
* @param imgarr 图片数组
* @param g 图像画笔对象
*/
public BufferedImage drawImage_03(int[][] imgarr,Graphics g) {
//创建缓冲图片
BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
// Graphics g1 = img.getGraphics();
for(int i=0;i<imgarr.length;i++) {
for(int j=0;j<imgarr[i].length;j++) {
int rgb = imgarr[i][j];
Color color =new Color(rgb);
int red = color.getRed();
int blue = color.getBlue();
int green = color.getGreen();
Color ncolor =new Color(255-red,255-green,255-blue);
g.setColor(ncolor);
g.fillRect(X+i,Y+j,1,1);
}
}
g.drawImage(img,X,Y,null);
return img;
}
/**
* 4、脸部提亮
* @param imgarr 图片数组
* @param g 图像画笔对象
* @return
*/
public BufferedImage drawImage_04(int[][] imgarr,Graphics g) {
BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
for(int i=0;i<imgarr.length;i++) {
for(int j=0;j<imgarr[i].length;j++) {
int rgb = imgarr[i][j];
Color color =new Color(rgb);
int red = color.getRed();
int blue = color.getBlue();
int green = color.getGreen();
int grey = (int)(red*0.299+green*0.587+blue*0.114);
Color ncolor = new Color(Math.abs(red-255+245),green,blue);
g.setColor(ncolor);
g.fillRect(X+i,Y+j,1,1);
}
}
g.drawImage(img,X,Y,null);
return img;
}
/**
* 5、灰度处理
* @param imgarr 图片数组
* @param g 图像画笔对象
* @return
*/
public BufferedImage drawImage_05(int[][] imgarr,Graphics g) {
//创建缓冲图片
BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
//获取缓冲区笔
for(int i=0;i<imgarr.length;i++) {
for(int j=0;j<imgarr[i].length;j++) {
int rgb = imgarr[i][j];
Color color =new Color(rgb);
int red = color.getRed();
int blue = color.getBlue();
int green = color.getGreen();
//int grey = (int)(red+blue+green)/3; 较为简单的方法
// RGB转换成灰度图像的方法
// Gray = R*0.299 + G*0.587 + B*0.114
//更精确的表示
int grey = (int)(red*0.299+green*0.587+blue*0.114);
Color ncolor = new Color(grey,grey,grey);
g.setColor(ncolor);
g.fillRect(X+i,Y+j,1,1);
}
}
g.drawImage(img,X,Y,null);
return img;
}
/**
* 6、二值化
* @param imgarr 图片数组
* @param g 图像画笔对象
* @return
*/
public BufferedImage drawImage_06(int[][] imgarr,Graphics g) {
BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
for(int i=0;i<imgarr.length;i++) {
for(int j=0;j<imgarr[i].length;j++) {
int rgb = imgarr[i][j];
Color color =new Color(rgb);
int red = color.getRed();
int blue = color.getBlue();
int green = color.getGreen();
//先进行灰度化处理
int grey = (int)(red*0.299+green*0.587+blue*0.114);
Color ncolor = new Color(grey,grey,grey);
//用灰度值大小与110进行比较(修改参数值可以得到不同的深浅度)
if(grey <110)
{
g.setColor (Color.BLACK);
}
else{
g.setColor (Color.WHITE);
}
g.fillRect (100 + i, 100 + j, 1, 1);
}
}
g.drawImage(img,X,Y,null);
return img;
}
/**
* 8、油画
* @param imgarr 图片数组
* 原理:每隔五个像素点取一个,然后用随机大小的椭圆填充每个像素点周围的区域
* @param g 图像画笔对象
* return
*/
public BufferedImage drawImage_08(int[][] imgarr,Graphics g) {
BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
for(int i=0;i<imgarr.length-5;i+=5) {
for(int j=0;j<imgarr[i].length-5;j+=5) {
int rgb = imgarr[i][j];
Color color =new Color(rgb);
g.setColor(color);
Random ran=new Random();
int r=ran.nextInt(20)+5;
g.fillOval(X+i,Y+j,r,r);
}
}
g.drawImage(img,X,Y,null);
return img;
}
/**
* 9、轮廓处理
* @param imgarr 图片数组
* @param g 图像画笔对象
* @return
*/
public BufferedImage drawImage_09(int[][] imgarr, Graphics g){
BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
for(int i = 0; i < imgarr.length-1; i++){
for(int j = 0; j < imgarr[i].length-1; j++){
int rgb = imgarr[i][j];
Color color = new Color (rgb);
int red = color.getRed ();
int green = color.getGreen ();
int blue = color.getBlue ();
int gray = (int) (red * 0.41 + green * 0.36 + blue * 0.23);
// 取出右下斜方向的像素按照 灰度值 作比较
int nrgb = imgarr[i + 1][j + 1];
Color ncolor = new Color (nrgb);
int nred = ncolor.getRed ();
int ngreen = ncolor.getGreen ();
int nblue = ncolor.getBlue ();
int ngray = (int) (nred * 0.41 + ngreen * 0.36 + nblue * 0.23);
if(Math.abs (gray - ngray) > 15){
g.setColor (Color.black);
} else{
g.setColor (Color.white);
}
g.fillRect (X + i, Y + j, 1, 1);
}
}
g.drawImage(img,X,Y,null);
return img;
}
/**
* 13、珠纹化
* @param imgarr 图片数组
* @param g 图像画笔对象
* 原理,每隔10取一个像素点,后用大小为9的圆填充
*/
public BufferedImage drawImage_13(int[][] imgarr,Graphics g) {
BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
for(int i=0;i<imgarr.length;i+=10) {
for(int j=0;j<imgarr[i].length;j+=10) {
int rgb = imgarr[i][j];
Color color =new Color(rgb);
g.setColor(color);
g.fillOval(X+i,Y+j,9,9);
}
}
g.drawImage(img,X,Y,null);
return img;
}