1

我想使用OpenCV在屏幕截图中统计选项卡的数量。我第一次裁剪我的形象限制为铬制表符。然后我使用边缘检测,Canny算法在铬中查找边缘。然后我使用Houghlines来查找标签数量,但是我没有通过Houghlines获得所需的输出。以下是我的代码和输出。如何使用OpenCV houghlines来统计屏幕截图中的标签数量?

import cv2 
import numpy as np 
import math 
from matplotlib import pyplot as plt 
img = cv2.imread('1.png') 

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
edges = cv2.Canny(gray,50,200,apertureSize = 3) 
cv2.imwrite('result.png',edges) 
lines = cv2.HoughLines(edges,1,np.pi/180,50) 

for rho,theta in lines[0]: 
    slope = 180*theta*1.0/np.pi 
    if slope > 110 and slope <148: # for identifying chrome tab angle (right slope line of each tab) 
    a = np.cos(theta) 
    b = np.sin(theta) 
    x0 = a*rho 
    y0 = b*rho 
    x1 = int(x0 + 1000*(-b)) 
    y1 = int(y0 + 1000*(a)) 
    x2 = int(x0 - 1000*(-b)) 
    y2 = int(y0 - 1000*(a)) 
    cv2.line(img,(x1,y1),(x2,y2),(0,0,255),3) 
cv2.imwrite('result2.png',img) 

Original cropped image Final Image

Firefox image

enter image description here

回答

5

很有意思:d 一个非常简单的解决办法是二值化您的图像和的上部区域,以确定直线图像并获取灰度值。然后你可以计算交叉点。下面是一个例子: Finding number of tabs from gray value profile

花哨的算法并不总是最好的解决方案。定义您想要做的事情,尽可能简单地找到解决方案。

这是我在C++中的解决方案。快速和肮脏)

#include "opencv2/imgproc.hpp" 
#include "opencv2/highgui.hpp" 
#include <vector> 
#include <stdlib.h> 
#include <stdio.h> 

using namespace cv; 
using namespace std; 

Mat src, binary, morph, gray, morph_rgb; 

/** 
*Compute number of tabs 
*/ 
int getNumberOfTabs(Mat& src, int start_col, int stop_col, int search_row, bool draw=false); 

/** 
* @function main 
*/ 
int main(int argc, char** argv) 
{ 
    const int morph_size = 2; 
    const int start_col = 5; 
    const int stop_col = 1750; 
    const int row_index = 2; 
    /// Load an image 
    src = imread("C:\\Users\\phili\\Pictures\\Tab.png", 1); 

    //Convert for binarization 
    cvtColor(src, gray, CV_RGB2GRAY); 
    threshold(gray, binary, 164, 255, 1); 

    //Remove icons and text on tabs 
    Mat element = getStructuringElement(CV_SHAPE_RECT, Size(2 * morph_size + 1, 2 * morph_size + 1), Point(morph_size, morph_size)); 
    morphologyEx(binary, morph, CV_MOP_OPEN, element); 

    int nmb_tabs = getNumberOfTabs(morph, start_col, stop_col, row_index, true); 

    imshow("Original", src); 
    imshow("Binary", binary); 
    imshow("Binary", morph); 


    /// Wait until user finishes program 
    while (true) 
    { 
     int c; 
     c = waitKey(20); 
     if ((char)c == 27) 
     { 
      break; 
     } 
    } 

} 

int getNumberOfTabs(Mat& src,int start_col,int stop_col, int row_index, bool draw) 
{ 
    int length = stop_col - start_col; 

    //Extract gray value profil 
    Mat profil = cv::Mat(0, length, CV_8U); 
    profil = src.colRange(start_col, stop_col).row(row_index); 

    Mat src_rgb; 
    if (draw) 
    {  
     cvtColor(src, src_rgb, CV_GRAY2RGB); 
     line(src_rgb, Point(start_col, row_index), Point(stop_col, row_index), Scalar(0, 0, 255), 2); 
    } 

    //Convolve profil with [1 -1] to detect edges 
    unsigned char* input = (unsigned char*)(profil.data); 
    vector<int> positions; 
    for (int i = 0; i < stop_col - start_col - 1; i++) 
    { 
     //Kernel 
     int first = input[i]; 
     int second = input[i + 1]; 
     int ans = first - second; 

     //Positiv or negativ slope ? 
     if (ans < 0) 
     { 
      positions.push_back(i + 1); 
      if(draw) 
       circle(src_rgb, Point(i + start_col, row_index), 2, Scalar(255,0, 0), -1); 
     } 
     else if (ans > 0) 
     { 
      positions.push_back(i); 
      if (draw) 
       circle(src_rgb, Point(i + start_col + 1, row_index), 2, Scalar(255,0, 0), -1); 
     } 

    } 
    if (draw) 
     imshow("Detected Edges", src_rgb); 
    //Number of tabs 
    return positions.size()/2; 
} 

,并与红色搜索线和蓝色检测到的边缘的结果: enter image description here

+0

嘿。我是这个主题的新手。你能告诉我你是如何将图像二值化的吗?我有一组图像。我想找到所有图片的标签数量的平均数 –

+1

我用[ImageJ](https://imagej.nih.gov/ij/)。它是一个开源的图像处理工具。您可以测试一些想法而无需创建新项目......! [这里](https://imagingbook.com/source/)你可以下载一些有用的插件。但基本上我将图像转换为8位,使用全局阈值(请参阅8位图像直方图)并进行二值化。在OpenCV中,您可以使用标记'CV_LOAD_IMAGE_GRAYSCALE'加载图像,或者使用'cv2.cvtColor'转换彩色图像,并使用'cv2.threshold'进行阈值处理。 – PSchn

+0

谢谢。我可以将图像二值化。你能帮我一下,我如何在一条线的帮助下计算交叉点?我使用Python的opencv –