绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
java openCV 识别条形码
2019-08-22 11:53:03

j我在尝试使用java openCV 识别条形码。在花边框时却这样。

我初步判断是,计算面积出现问题。

System.out.println("Welcome to OpenCV "+Core.VERSION);

Mat m =newMat(5,10, CvType.CV_8UC1,newScalar(0));

System.out.println("OpenCV:"+m);

Mat srcImage = Imgcodecs.imread("C:\\Users\\13543\\Desktop\\timg.jpg");//原始

Mat grayImage =newMat();//灰色

Mat gradientXImage =newMat();

Mat gradientYImage =newMat();

Mat gradientImage =newMat();

Mat blurImage =newMat();//降噪图

Mat thresholdImage =newMat();

Mat morphImage =newMat();

Mat resultFileNameSring =newMat();

ImageViewer imageViewer =newImageViewer(srcImage,"原图");

imageViewer.imshow();

if(srcImage.empty()){

System.out.println("image file read error");

return;

}

//图片转为灰度图片

if(srcImage.channels()==3){

Imgproc.cvtColor(srcImage,grayImage,Imgproc.COLOR_RGB2GRAY);

}else{

grayImage = srcImage.clone();

}

newImageViewer(grayImage,"灰色图").imshow();

//建立图像的梯度幅值(滤波器)

Imgproc.Scharr(grayImage,gradientXImage,CvType.CV_32F,1,0);

Imgproc.Scharr(grayImage,gradientYImage,CvType.CV_32F,0,1);

//因为我们需要的条形码在需要X方向水平,所以更多的关注X方向的梯度幅值,而省略掉Y方向的梯度幅值

Core.subtract(gradientXImage,gradientYImage,gradientImage);

//归一化为八位图像

Core.convertScaleAbs(gradientImage,gradientImage);

//看看得到的梯度图像是什么样子

newImageViewer(gradientImage,"3图").imshow();

//对图片进行相应的模糊化,使一些噪点消除

Imgproc.blur(gradientImage,blurImage,newSize(9,9));

//模糊化以后进行阈值化,得到到对应的黑白二值化图像,二值化的阈值可以根据实际情况调整

Imgproc.threshold(blurImage,thresholdImage,210,255,Imgproc.THRESH_BINARY);

//看看二值化图像

newImageViewer(thresholdImage,"4图").imshow();

//二值化以后的图像,条形码之间的黑白没有连接起来,就要进行形态学运算,消除缝隙,相当于小型的黑洞,选择闭运算

//因为是长条之间的缝隙,所以需要选择宽度大于长度

Mat kernel = Imgproc.getStructuringElement(MORPH_RECT,newSize(21,7));

Imgproc.morphologyEx(thresholdImage,morphImage,MORPH_CLOSE,kernel);

//看看形态学操作以后的图像

newImageViewer(morphImage,"5图").imshow();

//现在要让条形码区域连接在一起,所以选择膨胀腐蚀,而且为了保持图形大小基本不变,应该使用相同次数的膨胀腐蚀

//先腐蚀,让其他区域的亮的地方变少好是消除,然后膨胀回来,消除干扰,迭代次数根据实际情况选择

Imgproc.erode(morphImage,morphImage,Imgproc.getStructuringElement(MORPH_RECT,newSize(3,3)),newPoint(-1,-1),4);

Imgproc.dilate(morphImage,morphImage,Imgproc.getStructuringElement(MORPH_RECT,newSize(3,3)),newPoint(-1,-1),4);

//看看形态学操作以后的图像

newImageViewer(morphImage,"6图").imshow();

List contours =newArrayList();

List contourArea =newArrayList();

Mat hierarchy =newMat();

//接下来对目标轮廓进行查找,目标是为了计算图像面积

Imgproc.findContours(morphImage,contours,hierarchy,Imgproc.RETR_EXTERNAL,Imgproc.CHAIN_APPROX_SIMPLE);

System.out.println("============"+contours.size());

//计算轮廓的面积并且存放

for(int i =0; i < contours.size();i++)

{

contourArea.add(Imgproc.contourArea(contours.get(i)));

}

//找出面积大的轮廓

Double maxValue;Point maxLoc;

Core.MinMaxLocResult minMaxLocResult = Core.minMaxLoc(morphImage);

//minMaxLoc(contourArea, NULL,&maxValue,NULL,&maxLoc);

//minMaxLoc()

//Core.MinMaxLocResult

//Core.MinMaxLocResult minMaxLocResult = Core.minMaxLoc(morphImage,morphImage);//Core.minMaxLoc(morphImage);

maxValue = minMaxLocResult.maxVal;

maxLoc = minMaxLocResult.maxLoc;

System.out.println("x:"+maxLoc.x+" y:"+maxLoc.y+" maxVal:"+maxValue);

//

// System.out.println("*********Start*******");

List<MatOfPoint2f> newContours = new ArrayList<>();

for(MatOfPoint point : contours) {

MatOfPoint2f newPoint = new MatOfPoint2f(point.toArray());

newContours.add(newPoint);

}

/计算面积大的轮廓的小的外包矩形

//// MatOfPoint2f m2f = (MatOfPoint2f) contours.get((int)maxLoc.x);

RotatedRect minRect = minAreaRect(newContours.get((int)maxLoc.x));

//

//

//

//

//

////为了防止找错,要检查这个矩形的偏斜角度不能超标

////如果超标,那就是没找到

if(minRect.angle<2.0){

//找到了矩形的角度,但是这是一个旋转矩形,所以还要重新获得一个外包小矩形

Rect myRect = boundingRect(newContours.get((int)maxLoc.x));

////把这个矩形在源图像中画出来

rectangle(srcImage,myRect,newScalar(0,255,255),3,LINE_AA);

////把这个矩形在源图像中画出来

newImageViewer(srcImage,"7图").imshow();

}

分享好友

分享这个小栈给你的朋友们,一起进步吧。

应用开发
创建时间:2020-06-17 15:31:04
应用软件开发是指使用程序语言C#、java、 c++、vb等语言编写,主要是用于商业、生活应用的软件的开发。
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • 栈栈
    专家
戳我,来吐槽~